需求:记录每次用户请求Controller的Body参数,
思路:在每个Controller 该当中记录,容易漏记,如果在拦截器里面记的话,可以统一处理
问题:在postHandle 里面记,request.getInputStream() 取出来是空的,放在preHandle里面,就进不到 Controller 里面了。报:I/O error while reading input message; nested exception is java.io.IOException: Stream closed
原因:在拦截器已经读取了请求体中的内容,这时候请求的流中已经没有了数据,就是说HttpServletRequest请求体中的内容一旦读取就不不存在了,所以直接读取是不行的。
方案:对httprequest进行修饰,自定义的包装类来实现
添加 RequestLogFilter
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @Component @WebFilter(filterName = "requestLogFilter",urlPatterns = {"/*"}, initParams = {@WebInitParam(name = "ignoredUrl", value = ".css;.js;.jpg;.png;.gif;.ico;.html"), @WebInitParam(name = "filterPath", value = "/user/login#/user/registerUser")}) public class RequestLogFilter implements OncePerRequestFilter { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Override protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException { RequestLogWrapper requestWapper = null; if (servletRequest instanceof HttpServletRequest) { HttpServletRequest request = (HttpServletRequest) servletRequest; if(!request.getRequestURI().toLowerCase().contains("swagger")){ requestWapper = new RequestLogWrapper(request); } } if (requestWapper != null) { filterChain.doFilter(requestWapper, servletResponse); } else { filterChain.doFilter(servletRequest, servletResponse); } } @Override public void destroy() { logger.info(">>>> RequestLogFilter destroy <<<<"); } }
添加 RequestLogWapper
import cn.hutool.core.util.StrUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public class RequestLogWrapper extends HttpServletRequestWrapper { private Logger logger = LoggerFactory.getLogger(this.getClass()); private String requestBody; public String getRequestBody() { return requestBody; } public RequestLogWrapper(HttpServletRequest request) throws IOException { super(request); requestBody = getBodyString(request); String queryStr = StrUtil.isEmpty(request.getQueryString()) ? "" : "?" + request.getQueryString(); logger.info("{}{}\r\n{}", request.getRequestURI(), queryStr, requestBody); } @Override public ServletInputStream getInputStream() throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody.getBytes(StandardCharsets.UTF_8)); ServletInputStream servletInputStream = new ServletInputStream() { @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() throws IOException { return byteArrayInputStream.read(); } }; return servletInputStream; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } public String getBodyString(HttpServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } }
参考资源:
https://www.jianshu.com/p/ba2d5101ad90
https://blog.csdn.net/qq_38132283/article/details/107685797