@Value注解内使用SPEL自定义函数
@Value("#{T(com.cheetah.provider.utils.StringUtil).lower('${cluster.vendor.type}')}")
其中,${cluster.vendor.type}取的application.properties中的配置,com.cheetah.provider.utils.StringUtil#lower是用户自定义函数,
T()运算符的结果是一Class对象,它的真正价值在于它能够访问目标类型的静态方法和常量
自定义注解支持SpEL表达式
利用AOP生成用户操作日志
1.定义日志注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
//普通的操作说明
String value() default "";
//spel表达式的操作说明
String spelValue() default "";
}
2.定义spel解析工具类
public class SpelUtil {
private static SpelExpressionParser parser = new SpelExpressionParser();
private static DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
public static String generateKeyBySpEL(String spELString, ProceedingJoinPoint joinPoint) {
// 通过joinPoint获取被注解方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
// 使用spring的DefaultParameterNameDiscoverer获取方法形参名数组
String[] paramNames = nameDiscoverer.getParameterNames(method);
// 解析过后的Spring表达式对象
Expression expression = parser.parseExpression(spELString);
// spring的表达式上下文对象
EvaluationContext context = new StandardEvaluationContext();
// 通过joinPoint获取被注解方法的形参
Object[] args = joinPoint.getArgs();
// 给上下文赋值
for (int i = 0; i < args.length; i++) {
context.setVariable(paramNames[i], args[i]);
}
// 表达式从上下文中计算出实际参数值
return expression.getValue(context).toString();
}
}
3.定义切面类
@Aspect
@Component
public class SysLogAspect {
@Autowired
private LogService logService;
@Autowired
private HttpServletRequest request;
@Pointcut("@annotation(com.ztri.common.annotation.SysLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
saveSysLog(point, time);
return result;
}
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Log sysLog = new Log();
sysLog.setTime(time);
SysLog syslog = method.getAnnotation(SysLog.class);
if (syslog != null) {
//注解上的描述
if (StrUtil.isNotBlank(syslog.value())) {
sysLog.setOperation(syslog.value());
}
if (StrUtil.isNotBlank(syslog.spelValue())) {
String spelValue = SpelUtil.generateKeyBySpEL(syslog.spelValue(), joinPoint);
sysLog.setOperation(spelValue);
}
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
//请求的参数
Object[] args = joinPoint.getArgs();
try {
String params = JSONUtil.toJsonStr(args);
sysLog.setParams(params);
} catch (Exception e) {
}
//设置IP地址
sysLog.setIp(ServletUtil.getClientIP(request));
UserAgent ua = UserAgentUtil.parse(request.getHeader("User-Agent"));
sysLog.setBrowser(ua.getBrowser().toString());
//保存系统日志
logService.create(sysLog);
}
}
4.方法上使用日志注解
@ApiOperation("高级搜索(包含点击1.热门列表 2.更多跳转页面)")
@PostMapping("searchData")
@SysLog(spelValue = "'高级搜索' + #searchVo.keyWord")
public ResponseEntity<Object> searchData(@RequestBody SearchVo searchVo) throws IOException {
SearchDto searchDto = searchService.searchData(searchVo);
return new ResponseEntity<>(searchDto, HttpStatus.OK);
}
@ApiOperation("登录授权")
@PostMapping("/login")
@SysLog("用户登录")
public ResponseEntity<Object> login(@Validated(User.Create.class) @RequestBody LoginUser loginUser) {
return ResponseEntity.ok(authInfo);
}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。