声明:本文仅为个人观点,如有不当还请指出。
简介
本文采用spring aop机制,对方法进行日志记录与处理
环境构建
练习采用Gradle构建,如果使用Maven仅限参考。
plugins {
id 'org.springframework.boot' version '2.3.7.RELEASE'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
dependencies {
//web依赖
implementation 'org.springframework.boot:spring-boot-starter-web'
//aop注解依赖
implementation group: 'org.aspectj', name: 'aspectjweaver', version: '1.9.6'
//springBoot
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
正文
我们首先创建一个注解后面作为aop的切点,我这里定义的注解级别是方法级的,具体等级和参数都可以根据具体业务调整
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InterfaceLog {
String value() default "";
}
接下来我们来看关键逻辑
这里我们使用刚才创建的注解作为切点切入主方法,我们可以通过joinPoint拿到一些信息,然后可以将这些信息落库进行持久化
可以做接口访问人数、接口访问时间、访客信息等信息
注意:我们这里使用的@Aspect注解我们必须引入aspect的包不然使用aop的注解就会报错
@Component
@Aspect
@Slf4j
public class InterfaceLogAspect {
/**
* 配置切点
*/
@Pointcut("@annotation(刚才创建的注解全路径)")
public void interfaceLogPointcut() {
}
/**
* 配置切面
*
* @param joinPoint 环绕增强的连接点
* @return
* @throws Throwable 异常抛出
*/
@Around("interfaceLogPointcut()")
public Object interfaceLogAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
InterfaceLog declaredAnnotation = signature.getMethod().getDeclaredAnnotation(InterfaceLog.class);
// 日志持久化逻辑 这里使用打印代替
long start = System.currentTimeMillis();
log.info("开始执行时间 >>> " + start);
log.info("当前注解value >>> " + declaredAnnotation.value());
log.info("当前方法 >>> " + signature.getMethod());
result = joinPoint.proceed();
long end = System.currentTimeMillis();
log.info("结束执行时间 >>> " + end);
log.info("该接口总共耗时 >>> " + (end - start));
return result;
}
/**
* 异常捕获
*
* @param joinPoint 连接点
* @param e 异常捕获
*/
@AfterThrowing(pointcut = "interfaceLogPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
log.error("接口日志出现异常 >>> " + e.getMessage());
}
}
最后我们只需要把需要进行日志分析的方法打上该注解就可以了
@InterfaceLog("测试接口日志接口")
@PostMapping("testInterfaceLog")
public ResultData<?> testInterfaceLog() {
try {
log.info("测试接口日志接口");
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return ResultData.success("OK");
}
最后我们可以看下控制台的执行