是否支持在控制器操作参数中使用抽象命令对象?然后,根据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来检测传入的参数,并实例化正确的命令对象。这是我处理这类案件的唯一选择吗?
编辑:
来澄清这里的用例。我有两个域模型,它们共享相同的基类域模型,并且使用默认的table-per-hierarchy模型在数据库中建模继承。
在我的例子中,一个子域模型Model A需要一个名为body的不可空字符串,即一个文本条目,而另一个Model B则需要一个名为directUrl的不可空字符串。这些都是可以在平台上发布的公告。Model A是包含公告体的写入条目,而Model B则代表到包含实际公告的第三方站点的链接。
在这类场景中,我通常会在控制器操作中放置一个if语句来确定要实例化哪个相关的命令对象,但我希望有一个更干净的方法。
发布于 2017-05-09 11:31:11
不会是这样的。Grails需要一个具体的类(带有默认的公共构造函数)来对命令对象实例进行bind请求params。因此,这个类将被明确地定义为动作的参数。
发布于 2017-05-10 11:33:44
我想您将不得不手动调用绑定,这取决于映射包含的内容。
见RootModel.from(地图地图)。在您的案例地图中,将是来自Controller的params
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
}https://stackoverflow.com/questions/43857963
复制相似问题