欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-01 15:43:38
...

问题

公司使用 xml 方式流的方式发送请求,接收方使用 getInputStream() 获取数据,在过滤器中需要对请求的数据校验。过滤器校验完后无法重读 InputStream 中的数据。

原因

pos :标识当前流每次流读取的位置、 每读取一次pos 做一次位移、直至结束返回-1

因在读取一次后 pos值已经达到文件末尾、而 ServletInputStream 没有重写 rest() 方法、从而导致request.getInputStream 只能读取一次。

解决方法

public class AntiHttpServletRequestWrapper extends HttpServletRequestWrapper {
    
   private final byte[] body;
 
   public AntiHttpServletRequestWrapper(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 int read() throws IOException {
            return bais.read();
         }
      };
   }
 
}

使用

HttpServletRequest request = (HttpServletRequest)request0;
AntiHttpServletRequestWrapper antiHttpServletRequestWrapper = new AntiHttpServletRequestWrapper(request);
//获取请求中的参数
String param= StreamUtils.streamToString(antiHttpServletRequestWrapper.getInputStream());

工具类

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