getInputStream() はこのリクエストに対してすでに呼び出されています

最近ログシステムを作っています。ユーザーの操作記録を記録するモジュールがあります。リクエストパラメータ、返された結果、リクエストボディの内容を取得する必要があります。そしてボディを取得すると、次のことがわかります。ここに記事を記録してください!

エラー内容

getInputStream() has already been called for this request

その理由は、
ServletRequest の getReader() メソッドと getInputStream() メソッドは 1 回しか呼び出すことができず、両方を呼び出すことはできないためです。その後、フィルターで一度呼び出されると、コントローラーで再度呼び出すことはできません

解決策
まずリクエスト本文を保存し、次にサーブレットに付属する HttpServletRequestWrapper クラスを通じて getReader () メソッドと getInputStream () メソッドをオーバーライドして、保存された本文からストリームを読み取ります。次に、フィルター内の ServletRequest を MyRequestWrapper に置き換えます。

構成クラスの追加

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

おすすめ

転載: blog.csdn.net/weixin_43627706/article/details/125543803