Да, это поведение Grails по умолчанию, когда дело касается привязки данных к телу запроса. Когда вы читаете тело запроса через request.JSON
в своем фильтре, соответствующий входной поток будет закрыт или пуст. Итак, теперь Grails не может получить доступ к этому телу запроса для привязки к объекту команды.
Итак, вы можете либо получить доступ к телу запроса самостоятельно, либо использовать его с объектом команды, но не можете оба.
От Связывания тела запроса повелевать объекты заголовка http://grails.github.io/grails-doc/2.5.0/guide/theWebLayer.html#dataBinding:
Обратите внимание, что тело запроса разбираемый, чтобы сделать эту работу. Любая попытка прочитать тело запроса после этого не сработает с , соответствующий входной поток будет пустым. Действие контроллера может либо использовать объект команды, либо он может самостоятельно анализировать тело запроса (либо напрямую, либо ссылаясь на что-то вроде request.JSON), но не может обойти оба.
Итак, что вы пытаетесь достичь, невозможно напрямую. Но вы можете сделать что-то другое. В фильтре, прочитать входящее тело запроса и хранить в params
или session
(если фильтр передает запрос на контроллер), а затем вручную связать параметр в действии:
MyFilters.groovy
class MyFilters {
def filters = {
foo(/* your filter */) {
before = {
// Your checks
Map requestData = request.JSON as Map
session.requestData = requestData
return true
}
}
}
}
Теперь, в своем действии контроллера, а не делать:
class MyController {
def fooAction(MyCommandObject object) {
}
}
ли что-то вроде этого:
class MyController {
def fooAction() {
MyCommandObject object = new MyCommandObject(session.requestData)
// Clear from session to clear up the memory
session.requestData = null
}
}
Обновление: Вышеупомянутое решение, которое я предоставил, будет работать хорошо, но не является чистым. @JoshuaMoore предоставил ссылку с более чистым решением Http Servlet request lose params from POST body after read it once.
Хотя это может сработать, это не решение, которое будет хорошо масштабироваться. Учитывая использование данных сеанса и что вы никогда не очищаете данные из сеанса. Вам гораздо лучше использовать сервлет-фильтр, который реализует/расширяет 'HttpServletRequestWrapper' для повторного чтения. Эта тема хорошо освещена в Stackoverflow: http://stackoverflow.com/questions/10210645/http-servlet-request-lose-params-from-post-body-after-read-it-once ... Просто потому, что что-то работает , не означает, что он будет работать хорошо. Итак, для хобби-проекта ответ здесь прекрасен, но для реальных приложений это недальновидно. –
Спасибо @JoshuaMoore за ваш ответ. Ссылка, которую вы предоставили в awesome. Я пробовал это несколько месяцев назад, но не получил успеха из-за нехватки времени.Да, это более чистое решение из того, что я предоставил в качестве временного и быстрого решения. –
Вы подтвердили, что объекты команды не заполняются, если запрос 'request.JSON' обращается в фильтр, но я точно не понимаю, почему это так. Если я правильно помню, я все еще мог читать свойства из 'request.JSON' в методе действий, чей командный объект не был заполнен, потому что запрос' request.JSON' был обращен в фильтр. Если все свойства JSON все еще находятся в 'request.JSON', почему Grails не использует это для заполнения объекта команды. – XDR