Spring中的aware接口详情
587
2022-08-27
在@Value注解内使用SPEL自定义函数方式
目录@Value注解内使用SPEL自定义函数自定义注解支持SpEL表达式1.定义日志注解2.定义spel解析工具类3.定义切面类4.方法上使用日志注解
@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 {
/**
* 用于SpEL表达式解析.
*/
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]);
}
// 表达式从上下文中计算出实际参数值
/*如:
@annotation(key="#student.name")
method(Student student)
那么就可以解析出方法形参的某属性值,return “xiaoming”;
*/
return expression.getValue(context).toString();
}
}
3.定义切面类KDONL
@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 = UserAgenhttp://tUtil.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
SearchDto searchDto = searchService.searchData(searchVo);
return new ResponseEntity<>(searchDto, HttpStatus.OK);
}
@ApiOperation("登录授权")
@PostMapping("/login")
@SysLog("用户登录")
public ResponseEntity
return ResponseEntity.ok(authInfo);
}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~