什么是惯用的Groovy和Grails方式转换为Domain Model类?

时间:2016-02-19 20:46:48

标签: 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 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()

提前致谢

2 个答案:

答案 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会打字。键入涉及为任何对象分配类型。鸭子打字涉及为某种目的确定物体的适用性。

现在你必须要小心,因为这不适用于每个对象。它适用于AppleOrange的原因是因为它们具有完全相同的属性和属性类型集。

有人会想,为什么你会有两个行为完全相同的不同领域,但这显然是一个不同的讨论。

答案 1 :(得分:2)

在Grails 3中,域类实现了GormEntity特征,这是save()方法的来源。但这并未解决payloadfilenamecontentType属性的问题。

您可以做的是创建一个接口,该接口声明域类共同的方法和属性也实现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特征注入域类,但我不知道如果您明确使用它会发生什么。