前言
业务开发中,某些业务需要记录用户操作前后的日志,做一些log操作证据。
实现
- 在业务代码前后加save log 操作到 db
- 使用aop 不改变业务代码的情况下记录Log
aop记录日志到db
- 业务中全部打印日志
- 记录部分日志到db
部分日志需要记录到db
这里我们自定义Log注解
然后使用aop扫描次注解记录该日志操作
Log注解
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/**
* 模块
*/
String module() default "";
/**
* 描述
*/
String description() default "";
}
aop操作
package com.ly.traffic.ground.cxy.config;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Aspect
@Component
public class LogAspect {
private LoggerHelper log = LoggerHelper.getLoggerHelper(Constants.ModuleName.OPEN_API, LogAspect.class.getSimpleName());
/**
* 日志切入点
*/
@Pointcut("@annotation(com.xxxxxxxx.Log)")
public void logPointCut() {
}
private static final ThreadLocal<LogOperation> threadLocal = new ThreadLocal();
//某个查询bean service
@Autowired
private XXXXXXService xxxxxService;
//这里我们日志服务的url
@Value("${buss.api.url}")
private String URL;
@Before("logPointCut()")
public void doBefore(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Cookie[] cookies = request.getCookies();
if (cookies.length == 0) {
return;
}
String unionId = "";
for (int i = 0; i < cookies.length; i++) {
if ("unionId".equals(cookies[i].getName())) {
unionId = cookies[i].getValue();
break;
}
}
if (StringUtils.isEmpty(unionId)) {
return;
}
String paramter = AopUtil.getString(joinPoint);
LogOperation logOperation = new LogOperation(unionId);
logOperation.setDescription(paramter);
threadLocal.set(logOperation);
}
@AfterReturning(returning = "ret", pointcut = "logPointCut()")
public void doAfterReturning(Object ret) {
Result result = (Result) ret;
if (!ResultCode.OK.val().equals(result.getCode())) {
threadLocal.remove();
return;
}
try {
LogOperation logOperation = threadLocal.get();
//异步记录日志
ExecutorUtil.executor.submit(() -> {
logOperation.setOperateType("1");
logOperation.setPlatform(2);
StewardInfo stewardInfo = xxxxxService.findByUnionId(logOperation.getUnionId());
if (stewardInfo == null) {
return;
}
logOperation.setVcode(stewardInfo.getVcode());
logOperation.setAccount(stewardInfo.getMobile());
logOperation.setDescription( " 时间: " + LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateUtil.DATE_PATTERN_YYYY_MM_DD_HH_MM_SS)) + ", 修改后数据 : " + logOperation.getDescription());
URL = URL.replace("buspassopenapi","");
//add log send http
String json = JSON.toJSONString(logOperation);
String post = HttpUtils.post(URL+"/log/api/xxxxxx/saveLog", json);
log.infoLog("记录日志返回 : " + post + " send data : " + json + " url : " + URL);
});
} finally {
threadLocal.remove();
}
}
@AfterReturning(pointcut = "logPointCut()")
public void doAfter(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Method method = currentMethod(joinPoint, methodName);
Log log = method.getAnnotation(Log.class);
LogOperation logOperation = threadLocal.get();
//异步记录Log
String unionId = logOperation.getUnionId();
if (StringUtils.isEmpty(unionId)) {
return;
}
logOperation.setOperateModule(log.module()+":"+log.description());
}
@AfterThrowing(value = "logPointCut()", throwing = "throwable")
public void doAfterThrowing(Throwable throwable) {
// 保存异常日志记录
log.infoLog(throwable.getMessage());
threadLocal.remove();
}
/**
* 获取当前执行的方法
*
* @param joinPoint 连接点
* @param methodName 方法名称
* @return 方法
*/
private Method currentMethod(JoinPoint joinPoint, String methodName) {
/**
* 获取目标类的所有方法,找到当前要执行的方法
*/
Method[] methods = joinPoint.getTarget().getClass().getMethods();
Method resultMethod = null;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
resultMethod = method;
break;
}
}
return resultMethod;
}
}