Вызов render () из вспомогательного метода фильтра в Grails - PullRequest
5 голосов
/ 04 ноября 2010

У меня есть фильтры, подобные тем, которые определены ниже.Они запускают один и тот же блок кода в разных местах, поэтому, чтобы он оставался СУХИМ, я преобразовал этот код в метод doResponse ().

class MyFilters {

    def filters = {
        web(uri: '/web/**') {
            before = {

                // Do Stuff
                if (condition) {
                    doResponse(request, response, params)
                }
                return true
            }
            after = {
                if (condition) {
                    doResponse(request, response, params)
                }
                else {
                    // Do Stuff
                    doResponse(request, response, params)
                }

            }
            afterView = {
            }
        }
    }

    boolean doResponse(request, response, params) {
    // Do Stuff
        render(status: statusCode, contentType: "text/xml", encoding: "ISO-8859-1", text: text)
    // Do post-render stuff
        return false
    }
}

Однако это имеет неприятный побочный эффект.Похоже, что метод render () доступен только из закрытия фильтров.Есть ли какой-нибудь (аккуратный) способ для меня вызвать render () из doResponse ()?

Редактировать: я получаю ошибку:

groovy.lang.MissingMethodException: Нет подписи метода:MyFilters.render () применим для типов аргументов: (java.util.LinkedHashMap) значения: [[status: 500, contentType: text / xml, кодировка: ISO-8859-1, текст: ...]]

Ответы [ 3 ]

8 голосов
/ 04 ноября 2010

Передайте объект, который определяет метод render(..), в метод doRespond(..) и вызовите метод render(..) для этого объекта.

У замыканий есть некоторые неявные переменные , включаяих owner, что относится к закрытию родителя;так что мы можем передать это:

if (condition) {
    doResponse(owner, request, response, params)
}

doRespond(..) метод:

boolean doResponse(webFilter, request, response, params) {
    // Do Stuff
    webFilter.render(status: statusCode, contentType: 
        "text/xml", encoding: "ISO-8859-1", text: text)
    // Do post-render stuff
    return false
}
0 голосов
/ 05 ноября 2010

Вы можете попробовать это решение.

Заменить doResponse на закрытие:

 def doResponse = {
        render(status: statusCode, contentType: "text/xml", encoding: "ISO-8859-1", text: text)
        return false 
 }

Вызов doResponse (из закрытия фильтра):

def doResponseClosure = doResponse.clone()
doResponseClosure.delegate = delegate
// if it doesn't work, try adding: doResponseClosure.owner = owner
return doResponseClosure()

Клонирование выполняется по причинам параллелизма.

Я успешно использовал этот метод в других DSL Grails, таких как Criteria замыкания.

0 голосов
/ 04 ноября 2010

Не могли бы вы передать ссылку на функцию render в функцию doResponse?

есть:

if( condition ) {
  doResponse(request, response, params, this.&render )
}

и

boolean doResponse( request, response, params, renderFn ) {
// Do Stuff
    renderFn( status: statusCode, contentType: "text/xml", encoding: "ISO-8859-1", text: text )
// Do post-render stuff
    return false
}
...