在实际项目中可能需要监控每个接口的请求时间以及请求参数等相关信息,那么此时我们想到的就是两种实现方式,一种是通过拦截器实现,另一种则通过AOP自定义注解实现。本文介绍自定义注解实现方式!
自定义注解,四个元注解就不解释了前面有篇章介绍。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WebLog {
/**
* 日志信息描述
*/
String description() default "";
}
AOP实现:
1.@Order注解用来定义切面的执行顺序,数值越小优先级越高。
2.@Around环绕通知,我们可以自定义在什么时候执行@Before以及@After。
3.ThreadLocal针对每个线程都单独的记录。
@Aspect
@Component
public class WebLogAspect {
private static ThreadLocal<ProceedingJoinPoint> td = new ThreadLocal<>();
@Pointcut("@annotation(com.example.demo.annotation.WebLog)")
@Order(1)
public void webLog(){}
@Before("webLog()")
public void doBefor(JoinPoint point){
System.out.println("***********method before执行************");
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
System.out.println("请求URL:"+request.getRequestURL());
System.out.println("请求参数:"+ Arrays.toString(point.getArgs()));
System.out.println("***********method before结束************");
}
@Around("webLog()")
public Object doAround(ProceedingJoinPoint point) throws Throwable {
System.out.println("***********执行环绕方法开始************");
td.set(point);
long startTime = System.currentTimeMillis();
ProceedingJoinPoint joinPoint = td.get();
Object proceed = joinPoint.proceed();
System.out.println("执行耗时毫秒:"+ (System.currentTimeMillis()-startTime));
System.out.println("***********执行环绕方法结束************");
return proceed;
}
}
Controller
@RestController
public class LoginController {
@PostMapping("/user/login")
@WebLog(description = "用户登录接口")
public UserForm login(@RequestBody UserForm user){
return user;
}
}
测试结果