是否支持在控制器操作参数中使用抽象命令对象?那么根据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
来检测传入的参数并实例化正确的Command对象。这是我处理这种情况的唯一选择吗?
编辑:
在此澄清用例。我有两个共享相同基类域模型的域模型,并且我使用默认的table-per-hierarchy
模型在数据库中建模继承。
在我的情况下,其中一个子域模型Model A
需要一个名为body
的非可空字符串,即文本条目,而另一个Model B
需要一个不可为空的字符串名为directUrl
的字符串。这些代表可以在平台上发布的公告。 Model A
是包含公告正文的条目,而Model B
表示包含实际公告的第三方网站的链接。
在这种情况下,我传统上在控制器动作中放置一个if语句来确定要实例化哪个相关命令对象,但我希望有一个更干净的方法。
答案 0 :(得分:0)
它不会以这种方式工作。 Grails需要一个具体的类(使用默认的公共构造函数)来 <!DOCTYPE html>
<html lang="en" id="facebook" class="no_js">
<head><meta charset="utf-8" /><meta name="referrer" content="origin-when-crossorigin" id="meta_referrer" /><script>function envFlush(a){function b(c){for(var d in a)c[d]=a[d];}if(window.requireLazy){window.requireLazy(['Env'],b);}else{window.Env=window.Env||{};b(window.Env);}}envFlush({"ajaxpipe_token":"AXjKg9wJIltZEBjN","khsh":"0`sj`e`rm`s-0fdu^gshdoer-0gc^eurf-3gc^eurf;1;enbtldou;fduDmdldourCxO`ld-2YLMIuuqSdptdru;qsnunuxqd;rdoe-0unjdojnx-0unjdojnx0-0gdubi^rdbsduOdv-0`sj`e`r-0q`xm`r-0StoRbs`qhof-0mhoj^q`xm`r"});</script><style></style><script>__DEV__=0;CavalryLogger=false;</script><noscript><meta http-equiv="refresh" content="0; URL=/?_fb_noscript=1" /></noscript><title id="pageTitle">Facebook - Log In or Sign Up</title><meta property="og:site_name" content="Facebook" /><meta property="og:url" content="https://www.facebook.com/" /><meta property="og:image" content="https://www.facebook.com/images/fb_icon_325x325.png" /><meta property="og:locale" content="en_GB" /><script type="application/ld+json">{"\u0040context":"http:\/\/schema.org","\u0040type":"WebSite","name":"Facebook","url":"https:\/\/www.facebook.com\/"}
请求命令对象实例的参数。因此,这个类将明确地定义为动作的参数。
答案 1 :(得分:0)
我猜您必须根据地图包含的内容手动调用绑定 请参见RootModel.from(地图)。在你的情况下,Map将是来自Controller的参数
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
}