1.思路
- 在需要log的方法上添加自定义注解
- aop log注解,获取方法参数、返回值、调用时间保存至队列中
- 队列取log,保存至MongoDB
2.实现
- 所需包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--MongoDB-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.4</version>
</dependency>
<!--LomBok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
- 自定义注解 - AopLog.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopLog {
String value() default "未定义"; //自定义操作名称 - 比如:支付货款
String collectionName() default "log"; //日志记录到MongoDB的哪个集合中
}
- 需要一个日志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
}
- 日志操作类 - AopLogUtil.java
@Repository
public class AopLogUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(AopLogUtil.class);
@Autowired
private MongoTemplate mongoTemplate;
private static BlockingQueue<Log> 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;
}
}
}
}
- 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);
}
}
}
- 启动时开始读取队列中的log保存至MongoDB
@Component
@Order(1)
public class SaveAopLog implements CommandLineRunner {
@Autowired
private AopLogUtil aopLogUtil;
@Override
public void run(String... args) throws Exception {
aopLogUtil.save();
}
}
- application.yml
spring:
data:
mongodb:
host: 127.0.0.1
port: 27017
database: moexclog
网友评论