解决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"));
    }
}

 

转载于:https://www.cnblogs.com/eviltuzki/p/9186165.html

如果您的HttpServletRequest拦截器在读取一次请求数据之后再次读取时无法读取数据,可能是因为HttpServletRequest对象的输入流只能读取一次,如果您已经读取了它,那么它将不再可用。 为了解决这个问题,您可以将HttpServletRequest对象的请求数据读取到一个字节数组中,并将字节数组包装在一个新的HttpServletRequest对象中,然后将新的HttpServletRequest对象用于后续处理。 以下是一个示例: ```java public class MyInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 读取请求数据到字节数组中 byte[] requestBody = IOUtils.toByteArray(request.getInputStream()); // 创建新的HttpServletRequest对象,并将字节数组包装在里面 HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) { @Override public ServletInputStream getInputStream() throws IOException { return new ServletInputStreamWrapper(requestBody); } @Override public int getContentLength() { return requestBody.length; } @Override public long getContentLengthLong() { return requestBody.length; } }; // 将新的HttpServletRequest对象用于后续处理 // ... return true; } } ``` 在这个示例中,我们使用了IOUtils.toByteArray()方法将HttpServletRequest对象的输入流读取到一个字节数组中。然后,我们创建了一个新的HttpServletRequestWrapper对象,并将字节数组包装在里面。最后,我们将新的HttpServletRequestWrapper对象用于后续处理。 这样,即使HttpServletRequest对象的输入流只能读取一次,您也可以在拦截器中多次读取HttpServletRequest对象的请求数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值