SpringBoot用AOP统一处理请求日志

SpringBoot用AOP统一处理请求日志

有时候我们想记录请求参数,请求地址等信息,此时可以在Controller层通过日志方式直接记录,但是采用这种方式我们需要在每个方法中一一处理,代码冗余度很高;而且如果想改变日志记录内容等信息就得排查每一个方法都改一遍,可维护性差。此时,我们可以采用AOP面向切面编程的方式对请求日志进行统一处理。

1.引入Aop依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.编写切面类

@Component
@Aspect
public class LogAspect {
	
}

注:使用@Aspect注解将一个java类定义为切面类

3.在切面类中定义切入点

用@Pointcut定义切入点(即执行哪些方法时切入)

格式:

@Pointcut(expression)

其中,“expression”即匹配表达式常用的有:

1.execution()

格式:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
  • modifiers-pattern:访问修饰符匹配
  • ret-type-pattern:返回值类型匹配,*表示任何返回值
  • declaring-type-pattern:类路径匹配
  • name-pattern:方法名匹配(“*”表示任意方法名)
  • param-pattern:参数匹配(可以指定参数类型,多个参数用“,”隔开,也可以用“*”匹配任意参数类型,"…"表示零个或多个参数)
  • throws-pattern:异常类型匹配

其中带“?”的为可选项

** 例如:**

@Pointcut("execution(public * cn.lamb.controller.*.*(..))")

上述表达式表示匹配cn.lamb.controller包下所有类的所有方法并且返回值是任意类型的,参数为0个或者多个,也就是匹配cn.lamb.controller包下所有public修饰的方法。

2.@within、@target

用法:

@within(cn.lamb.annotation.MyTypeAnnotation)
@target(cn.lamb.annotation.MyTypeAnnotation)

以上均表示匹配类上标注了@MyTypeAnnotation注解的类下的任意方法

3.@annotation

用法:

@annotation(cn.lamb.annotation.MyTypeAnnotation)

表示匹配标注了@MyTypeAnnotation注解的方法

以上3种表达式均可单独使用,亦可通过“&& || 和!”即与或非的方式组合使用

具体用法:

//定义切入点
@Pointcut(表达式)
private void myPointcut(){}

@Before("myPointcut()")
public void doBefore(JoinPoint joinPoint){
   //方法执行前具体的处理逻辑
} 

@AfterReturning(pointcut = "myPointcut()",returning = "result")
public void doAfterReturning(Object result) throws Throwable {
   // 处理完请求,返回内容,此处方法参数result即为返回值        
}
@AfterThrowing("myPointcut()")
public void throwss(JoinPoint joinPoint){
   //出异常时处理逻辑
}
@After("myPointcut()")
public void after(JoinPoint joinPoint){
	//最终通知,不管方法正常执行结束还是出异常都执行此处理逻辑
}
@Around("myPointcut()")
public Object arround(ProceedingJoinPoint pjp) {
//环绕通知
	try {
		Object o =  pjp.proceed();
		return o;
	} catch (Throwable e) {
		e.printStackTrace();
		return null;
	}
}

附:

Pointcut表达式举例:

//任意公共方法:
execution(public * *(..))
//controller包里的任意方法的执行:
execution(* cn.lamb.controller.*.*(..))

//controller包中的类.
within(cn.lamb.controller.*)
//controller包和其所有子包里的类.
within(cn.lamb.controller..*)

//带有@MyAnnotation注解的所有类的任意方法.
@within(cn.lamb.annotation.MyAnnotation)
@target(cn.lamb.annotation.MyAnnotation)
//带有@MyAnnotation注解的任意方法.
@annotation(cn.lamb.annotation.MyAnnotation)
//匹配controller包里加了MyAnnotation注解的所有方法:
@Pointcut(execution(* cn.lamb.controller.*.*(..)) && @annotation(cn.lamb.annotation.MyAnnotation))
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值