2

我正在测试 Grails 静态编译,特别是 GrailsCompileStatic。该文档仅限于解释不支持哪些 Grails 动态特性。我的测试控制器非常简单,但我已经遇到了问题。

@GrailsCompileStatic
class UserController {

    UserService userService

    def list() {
        def model = [:]
        def model = request.JSON

        withFormat {
            json {
                render(model as JSON)
            }
        }
    }
}

编译应用程序时出现两个编译时错误。第一个关于对象上缺少JSON的属性,第二个关于闭包中request缺少方法的错误。jsonwithFormat

在我看来,我要么做错了什么,要么GrailsCompileStatic不能使用这些功能?

4

1 回答 1

3

关于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)返回 a Object,它是 aJSONObject或 a 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它的第一个参数是一个。然后,内部实现根据当前请求或响应内容类型确定要使用参数闭包的哪一部分。

如果您想弄清楚如何静态地执行此操作,请查看源代码
你可以扩展这个类,然后使用它的受保护方法,但我不知道它是否值得所有的麻烦,你会失去很多 Grails 的简洁性。但如果你真的想这样做,你可以。你不只是喜欢开源项目吗?:)

于 2015-08-28T11:25:10.123 回答