在@Value注解内使用SPEL自定义函数方式

作者:daijiguo 时间:2022-04-26 20:59:41 

@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.定义切面类

@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);
? ? }

来源:https://daijiguo.blog.csdn.net/article/details/99403458

标签:@Value注解,SPEL,自定义函数
0
投稿

猜你喜欢

  • Java细数IO流底层原理到方法使用

    2022-08-06 21:30:45
  • 浅谈@Aspect@Order各个通知的执行顺序

    2021-10-24 19:00:38
  • 通过String.intern()方法浅谈堆中常量池

    2022-07-06 05:14:01
  • 模拟打印机排队打印效果

    2023-12-13 13:26:22
  • SpringMVC数据输出相关知识总结

    2022-04-06 10:35:06
  • Spring Boot 项目发布到 Tomcat 服务器的操作步骤

    2023-10-28 09:39:05
  • java启动jar包将日志打印到文本的简单操作

    2021-12-05 10:42:21
  • C++11中的可变参数模板/lambda表达式

    2023-06-10 18:20:14
  • Android 6.0动态权限申请教程

    2023-09-26 16:43:56
  • Java实现基础银行ATM系统

    2021-06-02 23:56:40
  • 详解基于Spring Cloud几行配置完成单点登录开发

    2023-07-06 19:14:11
  • idea搭建SSM框架遇踩的坑(附完整过程)

    2023-06-23 09:53:07
  • SpringBoot整合BCrypt实现密码加密

    2021-12-09 20:01:08
  • Spring Boot产生环形注入的解决方案

    2023-11-08 20:14:04
  • springboot集成redis并使用redis生成全局唯一索引ID

    2023-11-28 05:42:39
  • JDK集合源码之解析TreeMap(一)

    2021-08-09 07:14:02
  • Java简易登录注册小程序

    2023-01-23 09:16:13
  • 安卓模拟器genymotion的安装与使用图文教程

    2021-12-13 19:28:36
  • Spring Boot中如何使用Swagger详解

    2023-09-27 18:13:58
  • C#识别出图片里的数字和字母

    2023-04-12 08:21:41
  • asp之家 软件编程 m.aspxhome.com