将Groovy和Grails惯用的方式转换为域模型类是什么?
考虑到Grails域类“Apple.groovy”和“Orange.groovy”没有严格的关联,以及从控制器调用的以下Grails服务:将Groovy和Grails惯用的方式转换为域模型类是什么?,grails,groovy,Grails,Groovy,考虑到Grails域类“Apple.groovy”和“Orange.groovy”没有严格的关联,以及从控制器调用的以下Grails服务: package test import grails.transaction.Transactional import javax.servlet.http.HttpServletRequest @Transactional class UploadService { def uploadApple(HttpServletRequest re
package test
import grails.transaction.Transactional
import javax.servlet.http.HttpServletRequest
@Transactional
class UploadService {
def uploadApple(HttpServletRequest request, Apple o) {
def file = request.getFile('payload')
o.payload = file.getBytes()
o.filename = file.originalFilename
o.contentType = file.contentType
o.save(flush:true)
}
def uploadOrange(HttpServletRequest request, Orange o) {
def file = request.getFile('payload')
o.payload = file.getBytes()
o.filename = file.originalFilename
o.contentType = file.contentType
o.save(flush:true)
}
}
如何用一种通用的方法来统一这段代码?我希望Groovy的可选类型能够为我处理这个问题,但是如果我从方法签名中删除类型,我似乎无法成功地调用.save()
提前感谢避免将
请求
传递给服务,并将文件
传递给服务。你是这样试的吗
def upload(file, obj) {
obj.payload = file.getBytes()
obj.filename = file.originalFilename
obj.contentType = file.contentType
obj.save(flush:true)
}
与Java不同,Groovy不进行duck类型化。键入涉及将类型指定给任何对象。Duck类型涉及确定对象是否适合某些用途
现在,您必须小心,因为这不会适用于所有对象。它适用于Apple
和Orange
的原因是它们都具有完全相同的属性集和属性类型
有人会想,为什么会有两个行为完全相同的不同域,但这显然是一个不同的讨论 避免将
请求
传递给服务,并将文件
传递给服务。你是这样试的吗
def upload(file, obj) {
obj.payload = file.getBytes()
obj.filename = file.originalFilename
obj.contentType = file.contentType
obj.save(flush:true)
}
与Java不同,Groovy不进行duck类型化。键入涉及将类型指定给任何对象。Duck类型涉及确定对象是否适合某些用途
现在,您必须小心,因为这不会适用于所有对象。它适用于Apple
和Orange
的原因是它们都具有完全相同的属性集和属性类型
有人会想,为什么会有两个行为完全相同的不同域,但这显然是一个不同的讨论 在Grails3中,域类实现了trait,这就是
save()
方法的来源。但这并不能解决有效负载
、文件名
和内容类型
属性的问题
您可以做的是创建一个接口,该接口声明两个域类通用的方法和属性,并实现org.grails.datastore.gorm.GormEntity
。然后,让域类实现接口:
interface Uploadable extends GormEntity {
byte [] payload
String filename
String contentType
}
class Apple implements Uploadable {
byte [] payload
String filename
String contentType
}
然后,您可以在服务中使用该接口
@Transactional
class UploadService {
def upload(HttpServletRequest request, Uploadable o) {
def file = request.getFile('payload')
o.payload = file.getBytes()
o.filename = file.originalFilename
o.contentType = file.contentType
o.save(flush:true)
}
}
注意:由于Grails自动将
GormEntity
特性注入域类,因此我不知道如果如图所示显式使用它会发生什么情况。在Grails 3中,域类实现该特性,这就是save()
方法的来源。但这并不能解决有效负载
、文件名
和内容类型
属性的问题
您可以做的是创建一个接口,该接口声明两个域类通用的方法和属性,并实现org.grails.datastore.gorm.GormEntity
。然后,让域类实现接口:
interface Uploadable extends GormEntity {
byte [] payload
String filename
String contentType
}
class Apple implements Uploadable {
byte [] payload
String filename
String contentType
}
然后,您可以在服务中使用该接口
@Transactional
class UploadService {
def upload(HttpServletRequest request, Uploadable o) {
def file = request.getFile('payload')
o.payload = file.getBytes()
o.filename = file.originalFilename
o.contentType = file.contentType
o.save(flush:true)
}
}
注意:由于Grails将
GormEntity
特性自动注入到域类中,我不知道如果如图所示显式使用它会发生什么。aaik,save()作为元类扩展实现。类型是否在方法签名中声明并不重要。您看到的错误是什么?错误500:内部服务器错误URI/Apple/save Class java.lang.NoSuchMethodError消息处理程序处理失败;嵌套的异常是java.lang.NoSuchMethodError:UploadService。u执行([Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;由UploadService引起。u执行([Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
您的u执行()
?不知道如何检查,这是grails create service Upload所生成的generates.aaik,save()作为元类扩展实现。无论类型是否在方法签名中声明。您看到的错误是什么?error 500:内部服务器错误URI/Apple/save Class java.lang.NoSuchMethodError消息处理程序处理失败;嵌套异常为java.lang.NoSuchMethodError:UploadService。\u执行([Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;由UploadService引起。u execute([Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
您的\uu execute()是什么
?不确定如何检查,它是由grails create service Upload
生成的。如果您还没有使用文件s,但是使用HttpServletRequest
s,您将从请求中获取文件,那么您可以在控制器中调用该服务:uploadService、 上传(request.getFile('payload'),苹果)
对于orange,您显然会通过orange
。但是在您将文件传递到服务之前,请确保它不是null或验证它。令人惊讶的是,它工作得如此之好。我不清楚为什么这会起作用,我的初始方法不会。是否愿意详细说明?谢谢。我会将其添加到我的答案中。您将如何从控制器调用它r如果您还没有使用文件
s,但是使用HttpServletRequest
s,那么您将从请求中获取文件。因此,在控制器中,您可以这样调用服务:uploadService.upload(request.getFile('payload'),apple)
对于orange,您显然会通过orange
。但是在您将文件传递到服务之前,请确保它不是null或验证它。令人惊讶的是,它工作得如此之好。我不清楚为什么这会起作用,我最初的方法不会。是否愿意详细说明?谢谢。我会将其添加到我的答案中。感谢您提供的信息性回复;决定接受另一个答案,因为它感觉更地道,尽管来自Java背景