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