我正在测试Grails静态编译,特别是GrailsCompileStatic。该文档仅限于解释不支持Grails动态功能的内容。我的测试控制器非常简单,但我已经遇到了问题。
@GrailsCompileStatic
class UserController {
UserService userService
def list() {
def model = [:]
def model = request.JSON
withFormat {
json {
render(model as JSON)
}
}
}
}
编译应用程序时,我遇到两个编译时错误。第一个关于JSON
对象上request
的遗失属性,以及json
关闭中withFormat
缺少方法的第二个错误。
对我来说,我做错了或GrailsCompileStatic
无法使用这些功能?
答案 0 :(得分:2)
request.JSON
通过request
类添加getJSON()
对象的ConvertersPluginSupport
方法。确切的行是:
private static void enhanceRequest() {
// Methods for Reading JSON/XML from Requests
def getXMLMethod = { -> XML.parse((HttpServletRequest) delegate) }
def getJSONMethod = { -> JSON.parse((HttpServletRequest) delegate)}
def requestMc = GrailsMetaClassUtils.getExpandoMetaClass(HttpServletRequest)
requestMc.getXML = getXMLMethod
requestMc.getJSON = getJSONMethod
}
正如您所看到的,它使用了动态调度机制,但幸运的是,这并不是什么大问题。您可以通过在控制器中的任何位置执行JSON.parse(request)
来简单地复制它。
虽然注意! JSON.parse(HttpServletRequest)
会返回Object
,JSONObject
或JSONArray
,因此如果您打算明确使用它们,而您正在静态编译,则必须进行投射它
您可以为控制器创建一个公共基类:
import org.codehaus.groovy.grails.web.json.JSONArray
import org.codehaus.groovy.grails.web.json.JSONObject
import grails.converters.JSON
@GrailsCompileStatic
class BaseController {
protected JSONObject getJSONObject() {
(JSONObject) JSON.parse(request)
}
protected JSONArray getJSONArray() {
(JSONArray) JSON.parse(request)
}
}
然后在您的控制器中,您可以简单地调用getJSONObject()
或getJSONArray
。这是一种解决方法,但会产生静态可编译的代码。
withFormat
这有点复杂。 withFormat
构造实际上是一个方法,它有一个Closure
作为它的第一个参数。然后,内部实现基于当前请求或响应内容类型计算出要使用的参数闭包的哪一部分。
如果您想了解如何静态执行此操作,请查看the source code 你可以扩展这个类,然后使用它的受保护的方法,但我不知道它是否值得所有的麻烦,你会失去Grails的简洁性。但如果你真的想这样做,你可以。你不喜欢开源项目吗? :)