近期有个日志记录的需求,近期已使用AOP将其实现,在此记录一下,也希望能帮助到有同样需求的码友。
大体思路是用AOP+自定义注解,在增删改的方法执行之前或之后,进行数据库日志记录。
一 定义一个自定义注解:
这里我定义了两个参数,description:对操作的详细描述(可以定义成json串,对数据进行规范处理)
operateType(操作类型)。这里可以根据自己业务需求对参数数量、类型进行自定义设置
import javax.interceptor.Interceptor;
import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConfigAopLogService {
String description() default "";
String operateType() default "";
}
二 定义一个切面类:
通过这个切面类来进行日志信息处理
@Aspect
@Component
public class LogAspect extends AdminBaseCtrl {
@Autowired
private EnterprisePlatLogRepo logRepo;
/**
* service层切点
*/
@Pointcut("@annotation(com.cbim.admin.service.ConfigAopLogService)")
public void serviceAspect(){
}
/**
* 获取注解参数,记录日志
* @param joinPoint 切入点参数
*/
@After("serviceAspect()")//这里我设置的是在操作方法执行之后进行日志记录,也可以设置成之后
public void doServiceLog(JoinPoint joinPoint){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
BackUserEntity backUser = getBackUser(request);
//将记录写入数据库
try {
ConfigConsoleLogBean logBean = new ConfigConsoleLogBean();
logBean.setCreateDate(new Date());
Long id = IdWorkerUtil.getInstance().nextId();
logBean.setId(id);
logBean.setDes("操作用户"+backUser.getId()+":"+getDes(joinPoint)+" 操作类型:"+getOperateType(joinPoint));
logRepo.save(logBean);
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 获取方法的描述信息
* @param joinPoint
* @return
*/
private String getDes(JoinPoint joinPoint) throws ClassNotFoundException {
//获取被代理对象名称
String targetName = joinPoint.getTarget().getClass().getName();
//获取目标方法名称
String methodName = joinPoint.getSignature().getName();
//获取传入目标方法的参数对象
Object[] arguments = joinPoint.getArgs();
//获取class对象
Class targetClass = Class.forName(targetName);
//获取对象中的所有方法
Method[] methods = targetClass.getMethods();
String des = "";
//下面是进行匹配,方法名和目标方法名相同,且参数相同,则获取注解内的相应参数,用来进行日志记录
for (Method method : methods) {
if (method.getName().equals(methodName)){
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length){
des = method.getAnnotation(ConfigAopLogService.class).description();
break;
}
}
}
return des;
}
/**
* 获取操作表的操作类型
* @param joinPoint
* @return
*/
//代码具体含义同上
private String getOperateType(JoinPoint joinPoint) throws ClassNotFoundException {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String operateType = "";
for (Method method : methods) {
if (method.getName().equals(methodName)){
if (method.getParameterTypes().length == args.length){
operateType = method.getAnnotation(ConfigAopLogService.class).operateType();
break;
}
}
}
return operateType;
}
最后,在需要进行记录的方法加上自定义注解就可以了
这里的description、operateType,可以配置一个枚举类,进行取值,这样会使代码更规范。