SpringAop + MongoDB 注解 记录 方法日志

1.思路

  1. 在需要log的方法上添加自定义注解
  2. aop log注解,获取方法参数、返回值、调用时间保存至队列中
  3. 队列取log,保存至MongoDB

2.实现

  1. 所需包
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.springframework.boot
            spring-boot-starter-aop
        
        
        
            org.springframework.boot
            spring-boot-starter-data-mongodb
        
        
        
            com.alibaba
            fastjson
            1.2.4
        

        
        
            org.projectlombok
            lombok
            1.16.10
        
  1. 自定义注解 - AopLog.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopLog {
    String value() default "未定义"; //自定义操作名称 - 比如:支付货款
    String collectionName() default "log"; //日志记录到MongoDB的哪个集合中
}
  1. 需要一个日志Model - Log.java
@Data //这个是lombok注解,如果不使用lombok,需要自己添加get、set方法
public class Log {
    private String annotationName;//自定义方法名 - AopLog.value
    private String methodName;//全限定方法名
    private Object[] methodArgs;//实参
    private Object methodResult;//方法返回值
    private Boolean normal;//状态 - 是否正常
    private Date date;//时间

    @Transient //不保存至MongoDB
    private String collectionName;//MongoDB Collection Name
}
  1. 日志操作类 - AopLogUtil.java
@Repository
public class AopLogUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(AopLogUtil.class);

    @Autowired
    private MongoTemplate mongoTemplate;

    private static BlockingQueue logs = new LinkedBlockingDeque<>();
    /**
     * @param log 添加Log到队列
     */
    public void add(Log log){
        logs.add(log);
    }
    private Log log;
    /**
     * 保存到MongoDB
     */
    public void save(){
        while(true){
            try {
                log = logs.take();
                LOGGER.info("待添加到MongoDB的日志:Json -> " + JSONObject.toJSONString(log));
                mongoTemplate.insert(log, log.getCollectionName());
            } catch (Exception e) {
                LOGGER.error("日志保存到MongoDB失败:Error -> " + e.getMessage());
            }finally {
                log = null;
            }
        }
    }
}
  1. aop
@Component
@Aspect
public class AopLogAspect {

    @Autowired
    private AopLogUtil aopLogUtil;

    @Pointcut("@annotation(AopLog)")
    public void aopLogCut(){}

    @Around("aopLogCut()")
    public Object AopLogCutAround(ProceedingJoinPoint joinPoint) throws Throwable{
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        AopLog aopLog = method.getAnnotation(AopLog.class);

        Log log = new Log();
        log.setMethodArgs(joinPoint.getArgs());
        log.setMethodName(method.toString());
        log.setCollectionName(aopLog.collectionName());
        log.setAnnotationName(aopLog.value());
        log.setDate(new Date());
        try {
            Object object = joinPoint.proceed();
            log.setMethodResult(object);
            log.setNormal(true);
            return object;
        } catch (Throwable throwable) {
            log.setMethodResult(throwable);
            log.setNormal(false);
            throw  throwable;
        } finally {
            aopLogUtil.add(log);
        }
    }
}
  1. 启动时开始读取队列中的log保存至MongoDB
@Component
@Order(1)
public class SaveAopLog implements CommandLineRunner {

    @Autowired
    private AopLogUtil aopLogUtil;

    @Override
    public void run(String... args) throws Exception {
        aopLogUtil.save();
    }
}
  1. application.yml
spring:
  data:
    mongodb:
      host: 127.0.0.1
      port: 27017
      database: moexclog

你可能感兴趣的:(SpringAop + MongoDB 注解 记录 方法日志)