request.getInputStream()只能调用一次解决

request.getInputStream()只能调用一次解决

起因:业务需要拦截器进行签名校验,拦截器中获取参数之后,导致@RequestBody注解报错(因为request.getInputStream()调用一次后失效)导致异常。这样就会导致controller 无法拿到数据。

解决方案

自定义一个类 BodyReaderHttpServletRequestWrapper.java

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
    //用于将流保存下来
    private byte[] requestBody = null;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        requestBody = StreamUtils.copyToByteArray(request.getInputStream());

    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);

        return new ServletInputStream() {

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

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

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

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

自定义 Filter 继承Filter

@WebFilter(filterName = "requestFilter", urlPatterns = "/*")
public class RequestFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest) {
            requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
        }
        if (requestWrapper == null) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }

    }

    @Override
    public void destroy() {
    }
}

启动类上增加注解

@ServletComponentScan("com.**.filter")

参考:https://www.cnblogs.com/weibanggang/p/13180469.html

posted @ 2021-02-25 15:55  永真  阅读(396)  评论(0)    收藏  举报