解决HttpServletRequest InputStream只能读取一次问题

Posted eviltuzki

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决HttpServletRequest InputStream只能读取一次问题相关的知识,希望对你有一定的参考价值。

 

在Filter中读取inputSeream读取一次之后就无法再次读取,解决办法如下:

public class LoggerHttpServletRequestWrapper extends HttpServletRequestWrapper {
   
   private final byte[] body;

   public LoggerHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
      super(request);
      body = StreamUtils.readBytes(request.getInputStream());
   }
   
   @Override
   public BufferedReader getReader() {
      return new BufferedReader(new InputStreamReader(getInputStream()));
   }
   
   @Override
   public ServletInputStream getInputStream() {
      final ByteArrayInputStream bais = new ByteArrayInputStream(body);
      return new ServletInputStream() {

         @Override
         public boolean isFinished() {
            return false;
         }

         @Override
         public boolean isReady() {
            return false;
         }

         @Override
         public void setReadListener(ReadListener readListener) {

         }

         @Override
         public int read() {
            return bais.read();
         }
      };
   }

}

  

调用如下

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    ServletRequest requestWrapper = null;
    if(request instanceof HttpServletRequest) {
        requestWrapper = new LoggerHttpServletRequestWrapper((HttpServletRequest) request);
        if (((HttpServletRequest) request).getMethod().equals("POST")){
            String path = ((HttpServletRequest) request).getServletPath();
            String param = StreamUtils.streamToString(requestWrapper.getInputStream());
            LoggerFactory.getLogger("filter."+path).info(param);
        }else if (((HttpServletRequest) request).getMethod().equals("GET")){
            String path = ((HttpServletRequest) request).getServletPath();
            String queryString = ((HttpServletRequest) request).getQueryString();
            LoggerFactory.getLogger("filter."+path).info(queryString);
        }


    }
    if(requestWrapper == null) {
        chain.doFilter(request, response);
    } else {
        chain.doFilter(requestWrapper, response);
    }
}

 

工具类如下

public class StreamUtils {

    /**
     * @param inputStream inputStream
     * @return 字符串转换之后的
     */
    public static String streamToString(InputStream inputStream) {
        try(BufferedReader br =new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) {
            StringBuilder builder = new StringBuilder();
            String output;
            while((output = br.readLine())!=null){
                builder.append(output);
            }
            return builder.toString();
        }  catch (IOException e) {
           throw new RuntimeException("Http 服务调用失败",e);
        }
    }

    

    public static byte[] readBytes(ServletInputStream inputStream) {
        return streamToString(inputStream).getBytes(Charset.forName("UTF-8"));
    }
}

 

以上是关于解决HttpServletRequest InputStream只能读取一次问题的主要内容,如果未能解决你的问题,请参考以下文章

解决HttpServletRequest InputStream只能读取一次问题

HttpServletRequest/HttpServletResponse乱码问题解决

无法找到类:java.lang.ClassNotFoundException: com.tt.javaweb.HttpServletRequest问题解决

Eclipse导入web项目报错找不到HttpServletRequest解决方法

HttpServletRequest参数只能获取一次的解决方案(参数拦截器 + 拦截器的注册)

解决 HttpServletRequest 流数据不可重复读