在spring中,通常可以使用切面编程方式对web请求记录操作日志。但是这种方式存在一个问题,那就是只能记录url中的请求参数,无法记录POST或者PUT请求的报文体,因为报文体是放在request对象的InputStream中的,只能读取一次。解决方法就是利用HttpServletRequestWrapper先读取InputStream,记录到一个头参数中,然后再重新放到InputStream中去。

代码如下:
先创建一个WrappedHttpServletRequest类:

import org.apache.commons.io.IOUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*; public class WrappedHttpServletRequest extends HttpServletRequestWrapper { private byte[] bytes;
private WrappedServletInputStream wrappedServletInputStream; public WrappedHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
// 读取输入流里的请求参数,并保存到bytes里
bytes = IOUtils.toByteArray(request.getInputStream());
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
this.wrappedServletInputStream = new WrappedServletInputStream(byteArrayInputStream); // 很重要,把post参数重新写入请求流
reWriteInputStream();
} /**
* 把参数重新写进请求里
*/
public void reWriteInputStream() {
wrappedServletInputStream
.setStream(new ByteArrayInputStream(bytes != null ? bytes : new byte[0]));
} @Override
public ServletInputStream getInputStream() throws IOException {
return wrappedServletInputStream;
} @Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(wrappedServletInputStream));
} /**
* 获取post参数,可以自己再转为相应格式
*/
public String getRequestParams() throws IOException {
return new String(bytes, this.getCharacterEncoding());
} private class WrappedServletInputStream extends ServletInputStream { public void setStream(InputStream stream) {
this.stream = stream;
} private InputStream stream; public WrappedServletInputStream(InputStream stream) {
this.stream = stream;
} @Override
public int read() throws IOException {
return stream.read();
} @Override
public boolean isFinished() {
return true;
} @Override
public boolean isReady() {
return true;
} @Override
public void setReadListener(ReadListener readListener) {}
}
}

再创建一个LogFilter对象:

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; @Component
@WebFilter(value = "/*", filterName = "logFilter")
@Slf4j
public class LogFilter implements Filter { @Override
public void init(FilterConfig filterConfig) throws ServletException {} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException { try {
WrappedHttpServletRequest requestWrapper =
new WrappedHttpServletRequest((HttpServletRequest) request); // 获取请求参数
String requestBody = requestWrapper.getRequestParams();
if (!StringUtils.isBlank(requestBody)) {
if (requestBody.length() >= 8192) {
requestBody = requestBody.substring(0, 8192);
}
request.setAttribute("request-body", requestBody); // 这里创建一个参数头,把要记录的报文放到参数头里面,在切面中读取这个参数头
} // 这里doFilter传入我们实现的子类
chain.doFilter(requestWrapper, response);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
} @Override
public void destroy() {}
}

最新文章

  1. 修正iOS从照相机和相册中获取的图片方向(转)
  2. 使用 Entity Framework Core 时,通过代码自动 Migration
  3. 确定比赛名次---HDU1285(拓扑排序)
  4. rabbitMQ publish丢包分析
  5. SpringMVC学习--文件上传
  6. mysql中datetime与timestamp的比较
  7. A+B Coming
  8. RUP(Rational Unified Process)统一软件过程概述
  9. 查看MYSQL数据库中所有用户及拥有权限
  10. C# 使用ManualResetEvent 进行线程同步
  11. 教程-EhLib70的安装方法
  12. oracle 之 内存—鞭辟近里(一)
  13. hdu1016
  14. js动态加载js css文件,可以配置文件后辍,防止浏览器缓存
  15. springMVC源码分析--AbstractControllerUrlHandlerMapping(六)
  16. 修改GDAL库支持RPC像方改正模型
  17. FIVE1
  18. Spark学习笔记——房屋价格预测
  19. vue项目webpack中Npm传递参数配置不同域名接口
  20. vue传参页面刷新数据丢失问题

热门文章

  1. hdu 1348【凸包模板】
  2. 网站SEO优化如何让百度搜索引擎绝的你的网站更有抓取和收录价值呢?_孙森SEO
  3. 压力测试之jmeter使用
  4. 【Maven】CentOS7使用Nexus3搭建maven私服
  5. ASP.NET MVC 实现伪静态
  6. JSON(2)JSONObject解析Josn和创建Jsonf示例
  7. 转 PHP Cookies
  8. JS格式化工具(转)
  9. 建造者模式以及php实现
  10. Android开发-下载网络图片并显示到本地