前提
今天在用AOP的环绕通知做用户操作记录时,发现一个小问题:怎么能动态的记录日志的备注?
比如用户添加一个资讯,那我们在日志记录上只能简单的看到一条 某某某添加一条资产,那么问题来了:添加一条什么资产呢?
往往我们想记录的日志记录不是这样的,我们想记录的是 某某某添加一条 XXXXX 资讯;这样我们的日志看起来就一清二楚了。
SPEL表达式
SpEL 使用 #{…} 作为定界符 , 所有在大括号中的字符都将被认为是 SpEL , SpEL 为 bean 的属性进行动态赋值提供了便利;
通过 SpEL 可以实现:
- 通过 bean 的 id 对 bean 进行引用。
- 调用方式以及引用对象中的属性。
- 计算表达式的值
- 正则表达式的匹配。
在前面我们了解了AOP的环绕通知的写法,今天我们只需要在上面加些处理的方法就好了,话不多说开始看代码吧!
在业务代码上的注解
加上表达式
注意 #{#webLoginPojo.userName}
这就是spel表达式
/**
* web用户登录
* @param webLoginPojo 账号 密码 验证码
* @param
* @return
*/
@OperLog(message = "登录:#{#webLoginPojo.userName}",operation = OperationType.LOGIN)
@RequestMapping(value = "/webLogin")
@ResponseBody
public ResultInfo<Object> webLogin(@RequestBody WebLoginPojo webLoginPojo){
try {
System.out.println("欢迎登录");
return new ResultInfo<Object>(ConnUtil.SUCCESS,"登录成功");
} catch (Exception e) {
e.printStackTrace();
}
return new ResultInfo<Object>(ConnUtil.ERROR,"服务器异常");
}
在自定义的切面处理类
里加上这个代码
message
:就是注入@OperLog
时的message
/**
* 解析SPEL
* @param message
* @param joinPoint
* @return
*/
private String executeTemplate(String message, ProceedingJoinPoint joinPoint)throws Exception{
ExpressionParser parser = new SpelExpressionParser();
LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
String[] params = discoverer.getParameterNames(method);
Object[] args = joinPoint.getArgs();
EvaluationContext context = new StandardEvaluationContext();
for (int len = 0; len < params.length; len++) {
context.setVariable(params[len], args[len]);
}
return parser.parseExpression(message, new TemplateParserContext()).getValue(context, String.class);
}
在原来的方法修改一下,调用executeTemplate()
方法
//获取操作
OperLog myLog = method.getAnnotation(OperLog.class);
if (myLog != null) {
String message = myLog.message();
String description = executeTemplate(message, proceedingJoinPoint);
sysLog.setMessage(description);//保存日志备注
}
这样 description
这个最后得到的就是一个完整动态的日志
最后
谢谢大家的参考、阅读;
可能大家在实际写代码的过程中有不一样的异常出错,大家可以留言一起讨论学习。