Servlets 如何在过滤器中获取HttpServletRequest的InputStream/getParameter而不使用它?

Servlets 如何在过滤器中获取HttpServletRequest的InputStream/getParameter而不使用它?,servlets,servlet-filters,query-parameters,Servlets,Servlet Filters,Query Parameters,有没有一种方法可以在不破坏控制器的情况下在过滤器中读取请求的主体 即: 使用@RequestParam或方法getParameter(字符串名称) 在控制器中获取请求的InputStream的可能性,即使您已经在过滤器中需要它 我从这篇文章中得到启发: 它复制然后缓存主体,然后提取参数映射并将其存储在属性formParameters中 公共类MultiReadHttpServletRequest扩展了HttpServletRequestWrapper{ private final FormHt

有没有一种方法可以在不破坏控制器的情况下在过滤器中读取请求的主体

即:

  • 使用
    @RequestParam
    或方法
    getParameter(字符串名称)
  • 在控制器中获取请求的InputStream的可能性,即使您已经在过滤器中需要它

    • 我从这篇文章中得到启发:

      它复制然后缓存主体,然后提取参数映射并将其存储在属性
      formParameters

      公共类MultiReadHttpServletRequest扩展了HttpServletRequestWrapper{
      private final FormHttpMessageConverter formConverter=新AllEncompassingFormHttpMessageConverter();
      多值映射参数;
      私有ByteArrayOutputStream缓存字节;
      公共MultiReadHttpServletRequest(HttpServletRequest请求)引发IOException{
      超级(请求);
      HttpInputMessage inputMessage=新的ServletServerHttpRequest(此){
      @凌驾
      公共InputStream getBody()引发IOException{
      返回getInputStream();
      }
      };
      formParameters=formConverter.read(null,inputMessage);
      }
      @凌驾
      公共ServletiInputStream getInputStream()引发IOException{
      if(cachedBytes==null)
      cacheInputStream();
      返回新的CachedServletInputStream();
      }
      @凌驾
      public BufferedReader getReader()引发IOException{
      返回新的BufferedReader(新的InputStreamReader(getInputStream());
      }
      @凌驾
      公共字符串getParameter(字符串名称){
      字符串queryStringValue=super.getParameter(名称);
      字符串formValue=this.formParameters.getFirst(名称);
      返回(queryStringValue!=null)?queryStringValue:formValue;
      }
      @凌驾
      公共映射getParameterMap(){
      映射结果=新建LinkedHashMap();
      枚举名称=this.getParameterNames();
      while(names.hasMoreElements()){
      String name=names.nextElement();
      put(name,this.getParameterValues(name));
      }
      返回结果;
      }
      @凌驾
      公共枚举getParameterNames(){
      集合名称=新LinkedHashSet();
      names.addAll(Collections.list(super.getParameterNames());
      names.addAll(this.formParameters.keySet());
      返回集合。枚举(名称);
      }
      @凌驾
      公共字符串[]getParameterValues(字符串名称){
      字符串[]queryStringValues=super.getParameterValues(名称);
      List formValues=this.formParameters.get(名称);
      if(formValues==null){
      返回querystringvalue;
      }
      else if(queryStringValues==null){
      返回formValues.toArray(新字符串[formValues.size()]);
      }
      否则{
      列表结果=新建ArrayList();
      addAll(Arrays.asList(queryStringValues));
      结果.addAll(formValues);
      返回result.toArray(新字符串[result.size()]);
      }
      }
      私有void cacheInputStream()引发IOException{
      /*缓存inputstream以便多次读取。对于
      *为了方便起见,我使用apache.commons IOUtils
      */
      cachedBytes=newbytearrayoutputstream();
      copy(super.getInputStream(),cachedBytes);
      }
      /*读取缓存请求正文的inputstream*/
      公共类CachedServletInputStream扩展了ServletInputStream{
      私有ByteArrayInputStream输入;
      公共缓存ServletInputStream(){
      /*从缓存的请求主体创建新的输入流*/
      input=newbytearrayinputstream(cachedBytes.toByteArray());
      }
      @凌驾
      public int read()引发IOException{
      返回input.read();
      }
      }
      }
      
      将整个请求数据缓冲在内存中。您可能不想在文件上传之类的事情上这样做。您是说在formParameters中?我的意思是,
      cachedBytes
      可能会很大。是的,我想知道它是否有那么大,因为最初它已经在某个地方,可以通过“request.getInputStream()”访问。所以,我们是否最终只使用
      IOUtils.copy(super.getInputStream(),cachedBytes)移动这个对象假设原始数据已被使用?request.getInputStream最初在接收请求时从请求中读取数据。这可以用于流式传输大数据,例如文件上传,而无需一次性将其读入内存。就像您可以使用FileInputStream从磁盘读取千兆字节的数据一样,即使它可能无法装入内存。