鉴于Grails域类“Apple.groovy”和“Orange.groovy”,并非严格相关,并且从控制器调用以下Grails服务:
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()
。
提前致谢
答案 0 :(得分:3)
避免将request
传递给服务并将File
传递给服务。你有这样的尝试吗?
def upload(file, obj) {
obj.payload = file.getBytes()
obj.filename = file.originalFilename
obj.contentType = file.contentType
obj.save(flush:true)
}
与Java不同,Groovy会打字。键入涉及为任何对象分配类型。鸭子打字涉及为某种目的确定物体的适用性。
现在你必须要小心,因为这不适用于每个对象。它适用于Apple
和Orange
的原因是因为它们具有完全相同的属性和属性类型集。
有人会想,为什么你会有两个行为完全相同的不同领域,但这显然是一个不同的讨论。
答案 1 :(得分:2)
在Grails 3中,域类实现了GormEntity特征,这是save()
方法的来源。但这并未解决payload
,filename
和contentType
属性的问题。
您可以做的是创建一个接口,该接口声明域类和共同的方法和属性也实现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
特征注入域类,但我不知道如果您明确使用它会发生什么。