Grails控制器动作抽象命令对象参数

Grails控制器动作抽象命令对象参数,grails,grails-controller,command-objects,Grails,Grails Controller,Command Objects,是否支持在控制器动作参数中使用抽象命令对象?然后根据JSON请求中的给定参数,它将选择正确的命令对象 例如: class SomeController { def someAction(BaseCommand cmd){ // cmd could be instance of ChildCommandOne or ChildCommandTwo } class BaseCommand { String paramOne }

是否支持在控制器动作参数中使用抽象命令对象?然后根据JSON请求中的给定参数,它将选择正确的命令对象

例如:

class SomeController {

    def someAction(BaseCommand cmd){
        // cmd could be instance of ChildCommandOne or ChildCommandTwo
    }

    class BaseCommand {
        String paramOne
    }

    class ChildCommandOne extends BaseCommand {
        String paramTwo
    }

    class ChildCommandTwo extends BaseCommand {
        String paramThree
    }

}
到目前为止,我一直在使用
request.JSON
检测传入的参数并实例化正确的命令对象。这是我处理这类案件的唯一选择吗

编辑:

在这里澄清用例。我有两个域模型,它们共享相同的基类域模型,并且我正在使用默认的
表/层次结构
模型对数据库中的继承进行建模

在我的例子中,一个子域模型
模型A
需要一个名为
body
的不可空字符串,这是一个文本条目,而另一个子域模型B需要一个名为
directUrl
的不可空字符串。这些是可以在平台上发布的公告
Model A
是包含公告正文的写入条目,而
Model B
表示指向包含实际公告的第三方网站的链接


在这种情况下,我通常会在控制器操作中使用if语句来确定要实例化哪个相关的命令对象,但我希望有一个更干净的方法。

它不会以这种方式工作。Grails需要一个具体的类(带有默认的公共构造函数)将请求参数绑定到命令对象实例。因此,这个类被明确定义为action的参数。

我想您必须根据map包含的内容手动调用binding。
请参阅RootModel.from(映射)。在您的情况下,映射将是来自控制器的参数

import static com.google.common.base.Preconditions.checkNotNull

import spock.lang.Specification
import spock.lang.Unroll

class CommandHierarchySpec extends Specification {

    @Unroll
    def "should create object of type #type for map: #map"() {
        when:
            def modelObj = RootModel.from(map)
        then:
            modelObj.class == type
        where:
            type   | map
            ModelA | [body: 'someBody', test: 'test']
            ModelB | [directUrl: 'directUrl', test: 'test']
    }

    def "should throw ISE when map does not contain neither body nor url"() {
        when:
            RootModel.from(a: 'b')
        then:
            thrown(IllegalStateException)
    }
}


abstract class RootModel {
    static RootModel from(Map map) {
        checkNotNull(map, "Parameter map mustn't be null")

        RootModel rootModel
        if (map.body) {
            rootModel = new ModelA()
        } else if (map.directUrl) {
            rootModel = new ModelB()
        } else {
            throw new IllegalStateException("Cannot determine command type for map: $map")
        }

        map.findAll { key, value -> rootModel.hasProperty(key) }
                .each {
            rootModel.setProperty(it.key, it.value)
        }

        rootModel
    }
}

class ModelA extends RootModel {
    String body
}

class ModelB extends RootModel {
    String directUrl
}

我认为这不是一个好方法,如果你有3个不同的命令,为什么不创建3个不同的动作呢?如果你解释一下你的用法,也许会更容易些case@rgrebski我已经更新了这个问题,以包含我的实际用例。另外,如果不在url映射中正式声明单独的端点,我如何区分这3个操作呢?这是一种有趣的方法。最后,我想我可以对有效的域命令对象进行注释,并使用鉴别器注释来注释区别于其他命令的属性。然后进行测试,直到我在参数映射中找到第一个具有匹配鉴别器属性的命令对象。那么传统上人们会如何处理这种情况呢?使用不同的端点来区分不同的命令?自己在特定实例上调用
bindData()
。很简单