使用AOP获取RequestBody

一开始使用spring拦截器拦截请求记录日志,对于请求路径、header这些都很好获取,唯独POST请求无法获取其中的RequestBody.

原因很明显,RequestBody是只能读取一次的,如果在拦截器中读取了,就无法通过@RequestBody注解去获取,因为这个数据是内存中的流数据.

那要如何做呢?明显就需要用到aop

利用AOP读取RequestBody

aop就是用来做切面的,具体概念这里不说了,自行谷歌.这里就讲具体问题的思路.

这里用aop去切入Controller里面所有public的方法,利用JoinPoint获取参数,从而得到RequestBody.
得到RequestBody后使用Spring Boot的日志打印

创建一个切面

1
2
3
@Aspect
@Component
public class RequestMapAspect {}
  • @Aspect注解表明这是一个切面
  • @Componet注册为组件,否则无法使用Spring Boot的日志

声明一个logger

1
private final Log log = LogFactory(this.getClass());
  • 这里的LogLogFactory均在org.apache.commons.logging包下,不是slf4j,不是logback也不是log4j!

声明切点

1
2
@Pointcut(value = "excution(public * cn.gaoyuexiang.controller.*.*(..))")
public void controllerLog() {}

编写Before获取参数

1
2
3
4
5
6
7
8
9
10
11
@Before("controllerLog()")
public void before(JoinPoint point) {
logger.info("controller aspect begging");
Object[] args = point.getArgs();
for (Object arg : args) {
logger.info("arg: " + arg);
}
String method = point.getSignature().getDeclaringTypeName() + '.' + point.getSignature().getName();
logger.info("aspect finishing");
logger.info("calling " + method);
}
  • JoinPoint.getArgs()可以得到目标方法的参数,返回类型为Object[]
  • RequestBody作为参数时,因为是在调用方法前已经被Spring读取并解析了,所以不存在重复读取的问题.调用目标方法时,Beforeaop被执行,拿到传递给目标的参数