springboot自定义log注解支持EL表达式
一、自定义注解package com.xxxx.common.aop;import com.xxx.common.enums.OperationLogModuleEnum;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retenti
·
一、自定义注解
package com.xxxx.common.aop;
import com.xxx.common.enums.OperationLogModuleEnum;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义操作日志记录注解
*
* @author minos
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/**
* 模块
*/
public OperationLogModuleEnum module() default OperationLogModuleEnum.USER_MANGER;
/**
* 描述
*/
public String describe() default "";
/**
* 操作人类别
*/
public String parameter() default "";
}
二、EL表达式支持
package com.xxxxx.common;
public class ExpressionRootObject {
private final Object object;
private final Object[] args;
public ExpressionRootObject(Object object, Object[] args) {
this.object = object;
this.args = args;
}
public Object getObject() {
return object;
}
public Object[] getArgs() {
return args;
}
}
package com.xxx.common;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.context.expression.CachedExpressionEvaluator;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ExpressionEvaluator<T> extends CachedExpressionEvaluator {
private final ParameterNameDiscoverer paramNameDiscoverer = new DefaultParameterNameDiscoverer();
private final Map<ExpressionKey, Expression> conditionCache = new ConcurrentHashMap<>(64);
private final Map<AnnotatedElementKey, Method> targetMethodCache = new ConcurrentHashMap<>(64);
public EvaluationContext createEvaluationContext(Object object, Class<?> targetClass, Method method, Object[] args) {
Method targetMethod = getTargetMethod(targetClass, method);
ExpressionRootObject root = new ExpressionRootObject(object, args);
return new MethodBasedEvaluationContext(root, targetMethod, args, this.paramNameDiscoverer);
}
public T condition(String conditionExpression, AnnotatedElementKey elementKey, EvaluationContext evalContext, Class<T> clazz) {
return getExpression(this.conditionCache, elementKey, conditionExpression).getValue(evalContext, clazz);
}
private Method getTargetMethod(Class<?> targetClass, Method method) {
AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass);
Method targetMethod = this.targetMethodCache.get(methodKey);
if (targetMethod == null) {
targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
if (targetMethod == null) {
targetMethod = method;
}
this.targetMethodCache.put(methodKey, targetMethod);
}
return targetMethod;
}
}
三、定义aop
package com.xxxx.common.aspect;
import com.xxxx.common.ExpressionEvaluator;
import com.xxxx.common.aop.Log;
import com.xxxx.common.utils.CurrentUserUtil;
import com.xxxx.common.utils.IpUtils;
import com.xxxx.common.utils.ServletUtils;
import com.xxxx.model.OperationLog;
import com.xxxx.service.OperationLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.expression.EvaluationContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 操作日志记录处理
*
* @author minos
*/
@Aspect
@Component
public class LogAspect {
@Autowired
OperationLogService operationLogService;
private ExpressionEvaluator<String> evaluator = new ExpressionEvaluator<>();
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
/**
* 配置织入点
*/
@Pointcut("@annotation(com.lets.psccs.common.aop.Log)")
public void logPointCut() {
}
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
handleLog(joinPoint);
}
/**
* 拦截异常操作
*
* @param joinPoint 切点
* @param e 异常
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint);
}
protected void handleLog(final JoinPoint joinPoint) {
addOPerationLog(joinPoint);
}
/**
* 写入日志
* @param joinPoint
*/
private void addOPerationLog(JoinPoint joinPoint) {
try {
// 获得注解
Log myLog = getAnnotationLog(joinPoint);
if (myLog == null) {
return;
}
// 请求的地址
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
String modelName = myLog.module().getName();
String parameter = getParameter(joinPoint);
String describe = myLog.describe().replace("parameter",parameter);
OperationLog operationLog=new OperationLog(CurrentUserUtil.currentUser());
operationLog.setModule(modelName);
operationLog.setIp(ip);
operationLog.setContent(describe);
operationLogService.insertSelective(operationLog);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private String getParameter(JoinPoint joinPoint) {
Log handler = null;
try {
handler = getAnnotationLog(joinPoint);
} catch (Exception e) {
e.printStackTrace();
}
if (joinPoint.getArgs() == null) {
return null;
}
EvaluationContext evaluationContext = evaluator.createEvaluationContext(joinPoint.getTarget(), joinPoint.getTarget().getClass(), ((MethodSignature) joinPoint.getSignature()).getMethod(), joinPoint.getArgs());
AnnotatedElementKey methodKey = new AnnotatedElementKey(((MethodSignature) joinPoint.getSignature()).getMethod(), joinPoint.getTarget().getClass());
return evaluator.condition(handler.parameter(), methodKey, evaluationContext, String.class);
}
/**
* 是否存在注解,如果存在就获取
*/
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(Log.class);
}
return null;
}
}
四、使用
/**
* 更新用户信息
*
* @param userVo
* @return
*/
@PostMapping("/update")
@ApiOperation("更新用户信息")
@Check({AuthorityConsts.XiTongSheZhi.BJYH})
@Log(module = OperationLogModuleEnum.USER_MANGER,describe ="编辑了parameter用户信息",parameter = "{#userVo.id}")
public AjaxResult update(@RequestBody @Validated UserVO userVo) {
User user = new User();
BeanUtils.copyProperties(userVo, user);
int update = userService.update(user);
return toAjax(update);
}
五、效果

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)