我使用Spring的@RequestBody
注释和MappingJacksonHttpMessageConverter
将我的请求的JSON POST数据映射到一个对象。然而,之后我想以String
形式阅读数据以进行一些额外的身份验证。但是当编组发生时,InputStream
中的HttpServletRequest
为空。从方法中删除@RequestBody
参数后,将POST数据读取到String
按预期工作。
我是否必须通过放弃@RequestBody
并以某种方式手动执行绑定或是否有更优雅的解决方案来妥协?
答案 0 :(得分:2)
所以,基本上你需要计算请求体的哈希值。优雅的方法是将装饰器应用于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
。在这种情况下,装饰器可以将计算的散列作为请求属性传递给处理程序方法。但是,您需要仔细映射此过滤器,以仅将其应用于对特定处理程序方法的请求。
答案 1 :(得分:0)
在你的urlMapping bean中,你可以声明其他拦截器的列表:
<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) {
...
}
}
答案 2 :(得分:0)
如果我理解正确的话,JAX-RS使用的一种常见方式(在绑定请求方面有点类似于Spring MVC)是首先“绑定”到某个中间原始类型(通常是byte [],但是String)也工作),并使用底层数据绑定器(杰克逊)手动绑定到对象。我经常这样做是为了能够完全自定义数据绑定的错误处理。