案例:将案例中的增,删,改相关接口的操作日志记录到数据库表中。
日志信息包括:操作人,操作时间,操作的类名,操作的方法名,方法参数,返回值,方法执行耗时
思路分析:
1,需要对所有业务类中的增,删,改方法添加统一功能,使用AOP技术最为方便,日志中包含返回值,方法执行耗时,所以我们要采用环绕通知
2,由于增,删,改方法名没有规律,使用execution表达式不好描述,所以采用@annotation切入点表达式,自定义@Log注解进行目标方法匹配
难点:获取当前登录用户
获取request对象,从请求头中获取到jwt令牌,解析令牌获取出当前用户的id.
步骤:
@Log注解: @Retention(RetentionPolicy.RUNTIME)//指定运行时生效 @Target(ElementType.METHOD)//指定作用在方法上 public @interface Log { }
切面类:
@Slf4j @Component @Aspect//指定当前类为切面类 public class LogAspect { @Autowired private HttpServletResponse response; @Autowired private OperateLogMapper operateLogMapper; //定义通知,为环绕通知 @Around("@annotation(com.ithema.anno.Log)") public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable { //操作人ID-当前登录人的ID //获取请求头中的jwt令牌,解析令牌 String jwt = response.getHeader("token"); Claims claims = JwtUtils.parseJWT(jwt); Integer operateUser =(Integer) claims.get("id"); //操作时间 LocalDateTime operatorTime = LocalDateTime.now(); //操作类名 String operatorName = joinPoint.getTarget().getClass().getName(); //操作方法名 String methodName = joinPoint.getSignature().getName(); //操作方法参数 Object[] args = joinPoint.getArgs(); String methodParam = Arrays.toString(args); long begin = System.currentTimeMillis(); //调用原始目标方法运行 Object result = joinPoint.proceed(); long end = System.currentTimeMillis(); //方法返回值 String returnValue = JSONObject.toJSONString(result); //操作耗时 long costTime = end - begin; //记录操作日志,需要调用OperateLogMapper接口中的insert方法记录操作日志 OperateLog operateLog=new OperateLog(null,operateUser,operatorTime,operatorName,methodName,methodParam,returnValue,costTime); operateLogMapper.insert(operateLog); return result; } }
将@Log注解添加到controller层的增,删,改的相关方法上