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 как это первый параметр. Внутренняя реализация затем выясняет, основываясь на текущем типе содержимого запроса или ответа, какую часть закрытия аргумента следует использовать.

Если вы хотите выяснить, как сделать это статически, взгляните на исходный код.
Вы можете расширить этот класс, а затем использовать его защищенные методы, но я не знаю, стоит ли он всех этих усилий, вы бы потеряли большую часть краткости Грааля. Но если вы действительно хотите это сделать, вы можете. Разве вы не любите проекты с открытым исходным кодом?:)

Другие вопросы по тегам