Grails 2.5.0 статическая компиляция, контроллеры и особенности grails
Я тестирую статическую компиляцию 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
не работает с этими функциями?
1 ответ
Около 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
как это первый параметр. Внутренняя реализация затем выясняет, основываясь на текущем типе содержимого запроса или ответа, какую часть закрытия аргумента следует использовать.
Если вы хотите выяснить, как сделать это статически, взгляните на исходный код.
Вы можете расширить этот класс, а затем использовать его защищенные методы, но я не знаю, стоит ли он всех этих усилий, вы бы потеряли большую часть краткости Грааля. Но если вы действительно хотите это сделать, вы можете. Разве вы не любите проекты с открытым исходным кодом?:)