在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() {}
}

Spring中操作日志记录web请求的body报文的更多相关文章

  1. Spring AOP进行日志记录

    在java开发中日志的管理有很多种.我一般会使用过滤器,或者是Spring的拦截器进行日志的处理.如果是用过滤器比较简单,只要对所有的.do提交进行拦截,然后获取action的提交路径就可以获取对每个 ...

  2. Spring AOP进行日志记录,管理

    在java开发中日志的管理有很多种.我一般会使用过滤器,或者是Spring的拦截器进行日志的处理.如果是用过滤器比较简单,只要对所有的.do提交进行拦截,然后获取action的提交路径就可以获取对每个 ...

  3. Spring Boot 之日志记录

    Spring Boot 之日志记录 Spring Boot 支持集成 Java 世界主流的日志库. 如果对于 Java 日志库不熟悉,可以参考:细说 Java 主流日志工具库 关键词: log4j, ...

  4. Winform开发框架之权限管理系统改进的经验总结(4)-一行代码实现表操作日志记录

    在前面介绍了几篇关于我的权限系统改进的一些经验总结,本篇继续这一系列主体,介绍如何一行代码实现重要表的操作日志记录.我们知道,在很多业务系统里面,数据是很敏感的,特别对于一些增加.修改.删除等关键的操 ...

  5. 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

    在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...

  6. (14)ASP.NET Core 中的日志记录

    1.前言 ASP.NET Core支持适用于各种内置和第三方日志记录提供应用程序的日志记录API.本文介绍了如何将日志记录API与内置提供应用程序一起使用. 2.添加日志提供程序 日志记录提供应用程序 ...

  7. 基于SqlSugar的开发框架循序渐进介绍(8)-- 在基类函数封装实现用户操作日志记录

    在我们对数据进行重要修改调整的时候,往往需要跟踪记录好用户操作日志.一般来说,如对重要表记录的插入.修改.删除都需要记录下来,由于用户操作日志会带来一定的额外消耗,因此我们通过配置的方式来决定记录那些 ...

  8. Spring AOP 完成日志记录

    Spring AOP 完成日志记录 http://hotstrong.iteye.com/blog/1330046

  9. springAOP实现操作日志记录,并记录请求参数与编辑前后字段的具体改变

    本文为博主原创,未经允许不得转载: 在项目开发已经完成多半的情况下,需要开发进行操作日志功能的开发,由于操作的重要性,需要记录下操作前的参数和请求时的参数, 在网上找了很多,没找到可行的方法.由于操作 ...

随机推荐

  1. TransposonPSI——转座子分析的入门自学

    最近需要做转座子分析,查找发现可以使用 TransposonPSI 来进行分析.但是登陆官网,该软件 update 时间为 2013 年,但是因为时间紧迫,暂时还没有进行其他方法的调研,所以先选用该软 ...

  2. Objective-C NSString/NSMutableString

    创建于完成: 2018/02/05 总览: http://www.cnblogs.com/lancgg/p/8404975.html  字符串类  简介  字符码: Unicode  NSString ...

  3. Linux 常用命令九 tar

    一.tar命令 tar命令用于打包,解包. gzip命令用于压缩,解压缩. bzip2命令用于压缩,解压缩. 这三个是在linux中常用的,还有一些不常用的. tar打包: wang@wang:~/w ...

  4. bzoj 1680: [Usaco2005 Mar]Yogurt factory【贪心】

    贪心,一边读入一边更新mn,用mn更新答案,mn每次加s #include<iostream> #include<cstdio> using namespace std; in ...

  5. Ocelot(六)- 架构图

    简介 Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由.请求聚合.服务发现.认证.鉴权.限流熔断.并内置了负载均衡器与Service Fabric.Butter ...

  6. 作为一个程序员,你了解 win 上有哪些必装的软件吗

    关于 win 的一些基础必知内容之前已经分享过,没有看过的可以戳此处→Windows 使用之那些你还不知道操作 新系统安装的第一个软件 Google Chrome 毫无疑问,作为程序员应该是首选的浏览 ...

  7. html 解决空格显示问题

    前端开发者都知道,在html中手动输入多个空格或者是回车,在页面解析的时候都被解析成一个空白显示,但有时候的需求要求显示多个空格,这个问题怎么解决呢?根绝我个人的经验,目前找到了以下集中解决办法: 1 ...

  8. 通过IDEA制作包含Java应程序的Docker镜像

    IDEA官网在IDEA中把Java App制作成Docker镜像并启动一个容器运行 在idea上使用docker作为java的开发环境[][] ubuntu+docker+docker-compose ...

  9. [POI2011]Temperature

    Description The Byteotian Institute of Meteorology (BIM) measures the air temperature daily. The mea ...

  10. 题解报告:poj 2559 Largest Rectangle in a Histogram(单调栈)

    Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base l ...