使用 Spring 的 @RequestBody 并随后读取 HttpServletRequest.getInputStream()
我使用 Spring 的 @RequestBody
注释和 MappingJacksonHttpMessageConverter
将请求的 JSON POST 数据映射到一个对象中。但是之后我想读取 String
形式的数据来进行一些额外的身份验证。但是当编组发生时,HttpServletRequest
中的InputStream
为空。一旦我从方法中删除了 @RequestBody
参数,将 POST 数据读入 String
就会按预期工作。
我是否必须通过放弃 @RequestBody 并以某种方式手动进行绑定来妥协,或者是否有更优雅的解决方案?
I'm mapping my request's JSON POST data into an object using Spring's @RequestBody
annotation and MappingJacksonHttpMessageConverter
. However after that I'd like to read the data in String
form to do some additional authentication. But when the marshalling has happened, the InputStream
in HttpServletRequest
is empty. Once I remove the @RequestBody
parameter from the method the reading of POST data into a String
works as expected.
Do I have to compromise by giving up the @RequestBody
and doing the binding somehow manually or is there a more elegant solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
因此,基本上您需要计算请求正文的哈希值。优雅的方法是将装饰器应用于
InputStream
。例如,在处理程序方法内部(在这种情况下,您不能使用
@RequestBody
并且需要手动创建HttpMessageConverter
):其中在重写的
中增量计算哈希值读取
方法。HashingInputStreamDecorator
的如果您创建
Filter
来应用装饰器,您还可以使用@RequestBody
。在这种情况下,装饰器可以将计算出的哈希值作为请求属性传递给处理程序方法。但是,您需要仔细映射此过滤器,以仅将其应用于对特定处理程序方法的请求。So, basically you need to compute a hash of the request body. The elegant way to do it is to apply a decorator to the
InputStream
.For example, inside a handler method (in this case you can't use
@RequestBody
and need to createHttpMessageConverter
manually):where hash is computed incrementally in overriden
read
methods ofHashingInputStreamDecorator
.You can also use
@RequestBody
if you create aFilter
to apply the decorator. In this case decorator can pass the computed hash to the handler method as a request attribute. However, you need to map this filter carefully to apply it only to the requests to specific handler method.在 urlMapping bean 中,您可以声明其他拦截器列表:
这些拦截器可以访问 HttpServletRequest,但如果您从流中读取数据,则参数映射器可能无法读取它。
In your urlMapping bean you can declare list of additional interceptors:
Those interceptors have access to HttpServletRequest, though if you read from the stream the chances are that parameter mapper won't be able to read it.
如果我理解正确的话,JAX-RS(在绑定请求方面与 Spring MVC 有点相似)使用的一种常见方法是首先“绑定”到一些中间原始类型(通常是 byte[],但 String 也可以) ,并使用底层数据绑定器 (Jackson) 手动将其绑定到对象。我经常这样做是为了能够完全自定义数据绑定的错误处理。
If I understand this correctly, one common way used with JAX-RS (which is somewhat similar to Spring MVC with respect to binding requests) is to first "bind" into some intermediate raw type (usually byte[], but String also works), and manually bind from that to object, using underlying data binder (Jackson). I often do this to be able to fully customize error handling of data binding.