Java 使用HttpServletRequestWrapper制作副本后缺少所需的请求正文

Java 使用HttpServletRequestWrapper制作副本后缺少所需的请求正文,java,json,spring-mvc,spring-boot,httprequest,Java,Json,Spring Mvc,Spring Boot,Httprequest,在我的项目中,我有一组api调用,这些调用应该通过特定的公共验证集进行过滤。在这种情况下,我必须在请求到达REST控制器之前拦截请求,读取请求正文,进行验证,如果请求通过验证,则将其传递给控制器 由于HttpServletRequest不能反序列化多次,因此我使用HttpServletRequestWrapper来复制实际请求。使用它制作的副本,我进行验证 以下是用于拦截请求的配置类 public class InterceptorConfig extends WebMvcConfigurerA

在我的项目中,我有一组api调用,这些调用应该通过特定的公共验证集进行过滤。在这种情况下,我必须在请求到达REST控制器之前拦截请求,读取请求正文,进行验证,如果请求通过验证,则将其传递给控制器

由于
HttpServletRequest
不能反序列化多次,因此我使用
HttpServletRequestWrapper
来复制实际请求。使用它制作的副本,我进行验证

以下是用于拦截请求的配置类

public class InterceptorConfig extends WebMvcConfigurerAdapter {

     @Autowired     
     CustomInterceptor customInterceptor;

     @Override  
     public void addInterceptors(InterceptorRegistry registry) { 
        registry.addInterceptor(customInterceptor).addPathPatterns("/signup/**");

     }   
}
这是我的
CustomInterceptor
类中的
preHandle
方法,它扩展了
HandlerInterceptorAdaptor

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    ServletRequest copiedRequest = new HttpRequestWrapper(request);

    Map<String, Object> jsonMap = mapper.readValue(copiedRequest.getInputStream(), Map.class);

    if(jsonMap.containsKey("userId")){
        long userId = jsonMap.get("userId");
        MyClass myObject= myAutowiredService.getMyObject(userId);
        if(myObject == null){
            response.setStatus(HttpStatus.SC_NOT_ACCEPTABLE);
            return false;
        } 
        // some more validations which end up returning false if they are met
    }
    return true;
}
一切都准备好了。现在,当我以
/signup/**
的模式向任何url发送请求时,所有验证都正常进行。但是,一旦请求命中控制器方法,就会弹出错误,说明请求主体不可用

缺少必需的请求正文:public com.mypackage.myResponseObject myControllerMethod(com.mypackage.myDTO)

我正在努力找到原因,也在努力找到克服这个问题的方法。在RequestWrapper类中,我是否做错了什么?还是有什么遗漏

帮我把这件事弄清楚


谢谢

问题似乎是您正在使用拦截器读取
HttpServletRequest
InputStream
并将其包装在
HttpRequestWrapper
中,但包装器从未返回

我认为你应该使用
过滤器

public class CustomFilter extends OncePerRequestFilter {
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        ServletRequest copiedRequest = new HttpRequestWrapper(request);

        Map<String, Object> jsonMap = mapper.readValue(copiedRequest.getInputStream(), Map.class);

        if(jsonMap.containsKey("userId")){
            long userId = jsonMap.get("userId");
            MyClass myObject= myAutowiredService.getMyObject(userId);
            if(myObject == null){
                response.setStatus(HttpStatus.SC_NOT_ACCEPTABLE);
                //return false;
            } 
            // some more validations which end up returning false if they are met
         }

         filterChain.doFilter(copiedRequest, (ServletResponse) response);
    }
}
公共类CustomFilter扩展了OncePerRequestFilter{
public void doFilterInternal(HttpServletRequest请求、HttpServletResponse响应、FilterChain FilterChain)抛出ServletException、IOException{
ServletRequest copiedRequest=新的HttpRequestWrapper(请求);
Map jsonMap=mapper.readValue(copiedRequest.getInputStream(),Map.class);
if(jsonMap.containsKey(“userId”)){
long userId=jsonMap.get(“userId”);
MyClass myObject=myAutowiredService.getMyObject(用户ID);
if(myObject==null){
响应。设置状态(HttpStatus.SC_不可接受);
//返回false;
} 
//还有一些验证,如果满足要求,则返回false
}
filterChain.doFilter(copiedRequest,(ServletResponse)响应);
}
}

您需要在
web.xml
WebApplicationInitializer

中使用此筛选器。您不是在阅读副本,而是在阅读实际请求。如果你想让它工作,你需要在一个过滤器中这样做,并传递包装好的请求。目前该请求仍在使用中。据我所知,我目前正在做的工作是制作一份实际请求的副本,并使用该副本进行验证。最后一个返回true的return语句将把实际请求传递给controller方法。在您发布的答案中,wt前进是复制的请求。不是吗?难道没有一种方法可以使用复制的东西来进行我们的验证和控制器的实际请求吗?据我所知,这是不可能的。因为您读取实际请求的InputStream,而流是一种方式。我按照您指示的方式实现了它。现在我面临的问题是,如何将其配置为仅对某些请求启用。url过滤现在是个问题嗨,我按照你的指示做了,但是我仍然得到一个
缺少必需的请求体:
在我的RestController中,带有@RequestBody
public class CustomFilter extends OncePerRequestFilter {
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        ServletRequest copiedRequest = new HttpRequestWrapper(request);

        Map<String, Object> jsonMap = mapper.readValue(copiedRequest.getInputStream(), Map.class);

        if(jsonMap.containsKey("userId")){
            long userId = jsonMap.get("userId");
            MyClass myObject= myAutowiredService.getMyObject(userId);
            if(myObject == null){
                response.setStatus(HttpStatus.SC_NOT_ACCEPTABLE);
                //return false;
            } 
            // some more validations which end up returning false if they are met
         }

         filterChain.doFilter(copiedRequest, (ServletResponse) response);
    }
}