一、自定义注解
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); }
五、效果