2015-07-24 3 views
4

В методе действий контроллера Grails 2.5.0 кажется, что свойства в модуле HTTP JSON не будут использоваться для привязки объекта команды, если request.JSON имеет был доступен в фильтре.Связывание объекта с контроллером Grails 2.5.0 после доступа к запросу. JSON в фильтре

Почему? Для меня это не имеет никакого смысла.

Можно ли использовать request.JSON в фильтре, а также для привязки объекта команды?

ответ

4

Да, это поведение 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.

+0

Хотя это может сработать, это не решение, которое будет хорошо масштабироваться. Учитывая использование данных сеанса и что вы никогда не очищаете данные из сеанса. Вам гораздо лучше использовать сервлет-фильтр, который реализует/расширяет 'HttpServletRequestWrapper' для повторного чтения. Эта тема хорошо освещена в Stackoverflow: http://stackoverflow.com/questions/10210645/http-servlet-request-lose-params-from-post-body-after-read-it-once ... Просто потому, что что-то работает , не означает, что он будет работать хорошо. Итак, для хобби-проекта ответ здесь прекрасен, но для реальных приложений это недальновидно. –

+0

Спасибо @JoshuaMoore за ваш ответ. Ссылка, которую вы предоставили в awesome. Я пробовал это несколько месяцев назад, но не получил успеха из-за нехватки времени.Да, это более чистое решение из того, что я предоставил в качестве временного и быстрого решения. –

+0

Вы подтвердили, что объекты команды не заполняются, если запрос 'request.JSON' обращается в фильтр, но я точно не понимаю, почему это так. Если я правильно помню, я все еще мог читать свойства из 'request.JSON' в методе действий, чей командный объект не был заполнен, потому что запрос' request.JSON' был обращен в фильтр. Если все свойства JSON все еще находятся в 'request.JSON', почему Grails не использует это для заполнения объекта команды. – XDR

 Смежные вопросы

  • Нет связанных вопросов^_^