使用Spring的@RequestBody并随后读取HttpServletRequest.getInputStream()
问题内容:
我正在使用Spring的@RequestBody
注释和将请求的JSON
POST数据映射到一个对象中MappingJacksonHttpMessageConverter
。但是之后,我想读取String
表格中的数据以进行其他身份验证。但是,当编组已经发生了,InputStream
在HttpServletRequest
为空。一旦我@RequestBody
从方法中删除了参数,POST数据的读取就可以String
正常工作了。
我是否必须通过@RequestBody
手动放弃绑定并以某种方式进行折衷来解决问题,还是有一个更优雅的解决方案?
问题答案:
因此,基本上,您需要计算请求正文的哈希值。做到这一点的优雅方法是将装饰器应用于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
要应用的装饰器,也可以使用。在这种情况下,装饰器可以将计算出的哈希值作为请求属性传递给处理程序方法。但是,您需要仔细映射此过滤器,以仅将其应用于对特定处理程序方法的请求。