获取行为日志对日常排查bug能够起到一定的帮助,使用自定义注解记录行为日志是非常便捷的一种方式
1.自定义注解
//指明了修饰的这个注解的使用范围,即被描述的注解可以用在哪里
@Target(ElementType.METHOD)
//指明修饰的注解的生存周期,即会保留到哪个阶段(RUNTIME: 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用)
@Retention(RetentionPolicy.RUNTIME)
//指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值
@Documented
public @interface RecordLog {
}
2.切面类
@Component
//把当前类标识为一个切面供容器读取
@Aspect
public class LogAspect {
@Resource
private SystemLogRepository logRepository;
//客户端请求,大部分信息可以在这里面获取到
@Resource
private HttpServletRequest request;
//将添加了RecordLog这个注解的地方作为一个切入点
@Pointcut("@annotation(com.xxx.RecordLog)")
public void logPointCut() {
}
/**
* 方法正常退出时执行
*/
@AfterReturning(pointcut = "logPointCut()")
public void doAfterReturning(JoinPoint joinPoint) {
try {
saveLog(joinPoint, null);
} catch (Exception e) {
e.printStackTrace();
}
}
//这个方法用于对切面获取到的数据进行处理,根据实际应用场景可以选择存到数据库或者打印到日志文件中
private void saveLog(JoinPoint joinPoint, String e) throws Exception {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
//获取ApiOperation注解的value,同样的方法可以获取你加在切入点方法上的注解的各种参数
ApiOperation annotation = method.getAnnotation(ApiOperation.class);
String userId = request.getParameter("userId");
SystemOperationLog operationLog = new SystemOperationLog();
operationLog.setOperationId(UUID.randomUUID().toString().replace("-", ""));
operationLog.setTitle(annotation.value());
//获取请求方法(POST、GET等)
operationLog.setBusinessType(request.getMethod());
//获取方法名
operationLog.setOperationMethod(methodSignature.getName());
operationLog.setUserId(userId);
operationLog.setUrl(request.getRequestURL().toString());
//获取调用方本地ip地址
operationLog.setUserIp(InetAddress.getLocalHost().getHostAddress());
//获取请求参数并转换成json格式
operationLog.setOperationParam(JSON.toJSONString(joinPoint.getArgs()));
operationLog.setStatus(e == null ? 0 : 1);
operationLog.setErrorMessage(e);
operationLog.setOperationTime(new Date());
logRepository.save(operationLog);
}
/**
* 方法抛出异常时执行
*/
@AfterThrowing(pointcut = "logPointCut()", throwing = "exception")
public void doAfterThrowing(JoinPoint joinPoint, Exception exception) {
try {
saveLog(joinPoint, exception.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
}
本篇文章中只用到了doAfterThrowing和doAfterReturning,通常根据业务场景选择切面方法在什么时候执行,以后用到其他场景再来更新
参考文章:
https://www.cnblogs.com/hyc-ana/p/9325618.html
https://www.cnblogs.com/jap6/p/10637429.html
https://blog.csdn.net/fz13768884254/article/details/83538709