背景

​ 众所周知request的输入流只能读取一次,不能重复读取,如果在过滤器或者拦截器中有业务需求对输入流进行一些其他操作,那么此处读取过后再到controller层就会报错,提示IO异常,这里采用实现HttpServletRequestWrapper自定义一个包装器的方式解决输入流不能重复读取的问题,并实现修改流的功能,下面直接上代码!

自定义Wrapper

/**
 * <p>
 * 构建HttpServletRequest包装器
 * </p>
 *
 * @author zhengshangjin
 * @version 1.0.0
 * @since 1.0.0
 * created on 2020-04-03
 */
@Slf4j
public class CoverHttpServletRequest extends HttpServletRequestWrapper {

    /**
     * 存储body数据的容器(这里存储为解析流后的JSON)
     */
    private String body;

    /**
     * 获取Body
     */
    public String getBody() {
        return this.body;
    }

    /**
     * 重写Body
     */
    public void setBody(String body) {
        this.body = body;
    }

    /**
     * copy stream
     *
     * @param request 当前的 HTTP 请求
     * @throws IllegalArgumentException if the request is null
     * @author zhengshangjin
     * created on 2020-04-03
     */
    public CoverHttpServletRequest(HttpServletRequest request) {
        super(request);
        body = RequestUtil.getRequestBody(request);
    }

    /**
     * override stream
     *
     * @param request 当前的 HTTP 请求
     * @param context 重写内容
     * @throws IllegalArgumentException if the request is null
     * @author zhengshangjin
     * created on 2020-04-03
     */
    public CoverHttpServletRequest(HttpServletRequest request, String context) {
        super(request);
        body = context;
    }

    /**
     * 默认行为在包装的请求对象上返回 getReader()
     *
     * @return BufferedReader
     * @author zhengshangjin
     * created on 2020-04-03
     */
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    /**
     * 默认行为在包装的请求对象上返回 getInputStream()
     *
     * @return BufferedReader
     * @author zhengshangjin
     * created on 2020-04-03
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

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

            @Override
            public void setReadListener(ReadListener listener) {
            }

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

}

解析流工具

    /**
     * 获取Request中Body
     *
     * @param request 当前的 HTTP 请求
     * @return String
     * @author zhengshangjin
     * created on 2020-04-03
     */
    public static String getRequestBody(HttpServletRequest request) {
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return stringBuilder.toString();
    }

Q.E.D.