Spring使用Spel表达式获取参数值-程序员宅基地

技术标签: spring  python  java  aop  redis  

一、依赖

 1 <dependency>
 2     <groupId>org.springframework.boot</groupId>
 3     <artifactId>spring-boot-starter-web</artifactId>
 4 </dependency>
 5 
 6 <!-- aop -->
 7 <dependency>
 8     <groupId>org.springframework.boot</groupId>
 9     <artifactId>spring-boot-starter-aop</artifactId>
10 </dependency>

二、注解

 1 @Target(ElementType.METHOD)
 2 @Retention(RetentionPolicy.RUNTIME)
 3 @Documented
 4 public @interface Limiter {
 5     /**
 6      * 使用spel表达式获取限流的key
 7      * @return
 8      */
 9     String value();
10 }

三、AOP切面的应用

 1 @Aspect
 2 @Component
 3 public class LimiterAspect {
 4     private ExpressionParser parser = new SpelExpressionParser();
 5     private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
 6 
 7     @Pointcut("@annotation(limiter)")
 8     public void pointcut(Limiter limiter) {
 9     }
10 
11     @Around("pointcut(limiter)")
12     public Object around(ProceedingJoinPoint pjp, Limiter limiter) throws Throwable {
13         Method method = this.getMethod(pjp);
14         String methodName = method.toString();
15 
16         //获取方法的参数值
17         Object[] args = pjp.getArgs();
18         EvaluationContext context = this.bindParam(method, args);
19 
20         //根据spel表达式获取值
21         Expression expression = parser.parseExpression(limiter.value());
22         Object key = expression.getValue(context);
23         //打印
24         System.out.println(key);
25         
26         return pjp.proceed();
27     }
28 
29     /**
30      * 获取当前执行的方法
31      *
32      * @param pjp
33      * @return
34      * @throws NoSuchMethodException
35      */
36     private Method getMethod(ProceedingJoinPoint pjp) throws NoSuchMethodException {
37         MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
38         Method method = methodSignature.getMethod();
39         Method targetMethod = pjp.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes());
40         return targetMethod;
41     }
42 
43     /**
44      * 将方法的参数名和参数值绑定
45      *
46      * @param method 方法,根据方法获取参数名
47      * @param args   方法的参数值
48      * @return
49      */
50     private EvaluationContext bindParam(Method method, Object[] args) {
51         //获取方法的参数名
52         String[] params = discoverer.getParameterNames(method);
53 
54         //将参数名与参数值对应起来
55         EvaluationContext context = new StandardEvaluationContext();
56         for (int len = 0; len < params.length; len++) {
57             context.setVariable(params[len], args[len]);
58         }
59         return context;
60     }

四、Controller

 1 @RestController
 2 public class TestController {
 3 
 4     //获取名为id的参数
 5     @Limiter("#id")
 6     @GetMapping("test")
 7     public String test(Long id){
 8         return "hello";
 9     }
10 }

五、获取对象(补充)

1、注解

1 @Limter(value = "#testObj")
2 public JSONObject test01(TestObj  testObj){
3       // ......      
4 }

多个切点同时获取

 1 /**
 2  * 设置操作日志切入点 记录操作日志 在注解的位置切入代码
 3  */
 4 //@Pointcut("@annotation(com.test.Limter)")
 5 @Pointcut("@annotation(limter)")
 6 public void operLogPointCut(Limter limter) {
 7 }
 8 
 9 @Pointcut("execution(public * com.test.aaa..*.*(..))")
10 public void operLogPointMethod() {
11 }

线程变量的使用,当前切面类中使用线程变量存储变量

 1 @Aspect
 2 @Component
 3 public class LogAspect {
 4 
 5     @Autowired
 6     private LogsService logsService;
 7     // 线程变量
 8     private ThreadLocal<String> threadLocal = new ThreadLocal<>();
 9 
10     /**
11      * 设置操作日志切入点 记录操作日志 在注解的位置切入代码
12      */

方法体中存入数据

public void savaData(){
    threadLocal.set("asdf");
}

在另一个方法体中获取当前线程数据

public void savaData(){
    String value = threadLocal.get();
}

切点多条件限制 &&

 1 @AfterReturning(value = "operLogPointCut(limter) && operLogPointMethod()", returning = "returnValue")
 2     public void saveOperLog(JoinPoint joinPoint, Limter limter, Object returnValue) {
 3         Object[] args = joinPoint.getArgs();
 4         // 从切面织入点处通过反射机制获取织入点处的方法
 5         MethodSignature signature = (MethodSignature) joinPoint.getSignature();
 6         // 获取切入点所在的方法
 7         Method method = signature.getMethod();
 8         EvaluationContext context = this.bindParam(method, args);
 9         Expression expression = parser.parseExpression(limter.value());
10 
11         TestObj testObj= expression.getValue(context, TestObj.class);
12         // ......
13         new Thread(() -> logsService.saveLogs(Obj...)).start();
14 
15         // 存入数据库后移除当前线程变量
16         threadLocal.remove();
17     }

 参考:

https://blog.csdn.net/weixin_45052750/article/details/105742934

 其他参考:

https://www.codeleading.com/article/30952452765/

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_39354297/article/details/113362777

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签