Использование Spring's @RequestBody и чтение HttpServletRequest.getInputStream () впоследствии - PullRequest
5 голосов
/ 04 ноября 2010

Я сопоставляю данные JSON POST моего запроса в объект, используя аннотацию Spring * @RequestBody и MappingJacksonHttpMessageConverter. Однако после этого я хотел бы прочитать данные в форме String, чтобы выполнить дополнительную аутентификацию. Но когда сортировка произошла, InputStream в HttpServletRequest пусто. Как только я удаляю параметр @RequestBody из метода, чтение данных POST в String работает как ожидалось.

Нужно ли идти на компромисс, отказавшись от @RequestBody и сделав привязку как-то вручную, или есть более элегантное решение?

Ответы [ 3 ]

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

Итак, в основном вам нужно вычислить хэш тела запроса. Элегантный способ сделать это - применить декоратор к InputStream.

Например, внутри метода обработчика (в этом случае вы не можете использовать @RequestBody и вам нужно создать HttpMessageConverter вручную):

@RequestMapping(...)
public void handle(HttpServletRequest request) throws IOException {
    final HashingInputStreamDecorator d = 
        new HashingInputStreamDecorator(request.getInputStream(), secretKey);
    HttpServletRequest wrapper = new HttpServletRequestWrapper(request) {
        @Override
        public ServletInputStream getInputStream() throws IOException {
            return d;
        }
    };

    HttpMessageConverter conv = ...;
    Foo requestBody = (Foo) conv.read(Foo.class, new ServletServerHttpRequest(wrapper));
    String hash = d.getHash();

    ...
}

где хэш вычисляется постепенно в переопределенных read методах HashingInputStreamDecorator.

Вы также можете использовать @RequestBody, если создаете Filter для применения декоратора. В этом случае декоратор может передать вычисленный хэш методу обработчика как атрибут запроса. Однако вам необходимо тщательно сопоставить этот фильтр, чтобы применять его только к запросам к конкретному методу-обработчику.

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

Если я правильно понимаю, один из распространенных способов, используемых с JAX-RS (который в некоторой степени аналогичен Spring MVC в отношении запросов на связывание), заключается в том, чтобы сначала «связать» в некоторый промежуточный необработанный тип (обычно byte [], но String).также работает), и вручную связать его с объектом, используя базовый механизм связывания данных (Джексон).Я часто делаю это, чтобы иметь возможность полностью настроить обработку ошибок привязки данных.

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

В вашем компоненте urlMapping вы можете объявить список дополнительных перехватчиков:

  <bean id="urlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="interceptors">
      <list>
        <bean class="org.foo.MyAuthInterceptor"/>
      </list>
    </property>
  </bean>

Эти перехватчики имеют доступ к HttpServletRequest, хотя, если вы читаете из потока, есть вероятность, что преобразователь параметров не сможетпрочитайте это.

public class AuthInterceptor extends HandlerInterceptorAdapter {

  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    ...
  }

  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav) {
    ...
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...