我将我的请求的JSON帖子数据映射到使用Spring的对象中 @RequestBody 注释和 MappingJacksonHttpMessageConverter. 。但是之后,我想阅读数据 String 表格进行一些其他身份验证。但是,当召集了时, InputStreamHttpServletRequest 是空的。一旦我删除了 @RequestBody 该方法的参数将帖子数据读取到一个 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();

    ...
}

在哪里计算哈希在Overriden中逐步计算 read 方法 HashingInputStreamDecorator.

您也可以使用 @RequestBody 如果您创建一个 Filter 应用装饰器。在这种情况下,装饰器可以将计算的哈希作为请求属性传递给处理程序方法。但是,您需要仔细映射此过滤器,以仅将其应用于特定处理程序方法的请求。

其他提示

在您的URL图中,您可以声明其他拦截器的列表:

  <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) {
    ...
  }
}

如果我正确理解这一点,则与JAX-RS一起使用的一种常见方法(与绑定请求相对于Spring MVC有些相似)是首先“绑定”到某些中间的原始类型(通常是字节[],但字符串也可以工作)并使用基础数据活页夹(Jackson)手动将其与对象绑定。我经常这样做,以便能够完全自定义数据绑定的错误处理。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top