getInputStream() has already been called for this request

Recently, I am working on a log system. There is a module in it to record user operation records. You need to get the request params, the returned result, and the content in the requestbody. Then when you fetch the body, you find that you can’t get it. Here Record the article!

Error content

getInputStream() has already been called for this request

The reason is that
the getReader() and getInputStream() methods of ServletRequest can only be called once, and cannot be called both. Then if it is called once in Filter, it cannot be called again in Controller

Solution
Save the Request Body first, and then override the getReader () and getInputStream () methods through the HttpServletRequestWrapper class that comes with the Servlet to read the stream from the saved body. Then replace ServletRequest with MyRequestWrapper in Filter.

Add configuration class

RequestWrapper.java

package top.fate.config;

import org.apache.poi.util.IOUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @auther:Wangxl
 * @Emile:[email protected]
 * @Time:2022/6/30 16:24
 */
public class RequestWrapper extends HttpServletRequestWrapper {
    
    

    private final byte[] body;

    public RequestWrapper(HttpServletRequest request) throws IOException {
    
    
        super(request);
        body = IOUtils.toByteArray(request.getInputStream());
    }

    @Override
    public BufferedReader getReader() throws IOException {
    
    
        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();
            }
        };
    }
}

HttpServletRequestReplacedFilter.java

package top.fate.config;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @auther:Wangxl
 * @Emile:[email protected]
 * @Time:2022/6/30 16:35
 */
public class HttpServletRequestReplacedFilter implements Filter {
    
    

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        ServletRequest servletWrapper = null;
        if (servletRequest instanceof HttpServletRequest) {
    
    
            servletWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
        }
        if (servletRequest == null) {
    
    
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
    
    
            try {
    
    
                filterChain.doFilter(servletWrapper, servletResponse);
            } catch (IOException e) {
    
    
                e.printStackTrace();
            } catch (ServletException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_43627706/article/details/125543803
Recommended