RuoYi-Vue-Plus (SPEL 表达式)

 RuoYi-Vue-Plus 中SPEL使用

DataScopeType 枚举类中:
/*** 部门数据权限*/DEPT("3", " #{#deptName} = #{#user.deptId} ", " 1 = 0 "),
PlusDataPermissionHandler 拦截器中定义了解析器:

        buildDataFilter 方法中根据注解的key value来进行SPEL解析:key作为占位符,value 设置进原生sql

@Slf4j
public class PlusDataPermissionHandler {  /*** spel 解析器*/private final ExpressionParser parser = new SpelExpressionParser();private final ParserContext parserContext = new TemplateParserContext();/*** 构造数据过滤sql*/private String buildDataFilter(DataColumn[] dataColumns, boolean isSelect) {。。。。。省略代码for (DataColumn dataColumn : dataColumns) {if (dataColumn.key().length != dataColumn.value().length) {throw new ServiceException("角色数据范围异常 => key与value长度不匹配");}if (!StringUtils.containsAny(type.getSqlTemplate(),Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new))) {continue;}//1- 设置注解变量 key 为表达式变量 value 为变量值for (int i = 0; i < dataColumn.key().length; i++) {context.setVariable(dataColumn.key()[i], dataColumn.value()[i]);}//2- 解析sql模板并填充String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class);conditions.add(joinStr + sql);isSuccess = true;}。。。。。省略代码}

一、概念

表达式语言给静态Java语言增加了动态功能。

SpEL是单独模块,只依赖于core模块,不依赖于其他模块,可以单独使用。

SpEL支持如下表达式:

一、基本表达式: 字面量表达式、关系,逻辑与算数运算表达式、字符串连接及截取表达式、三目运算及Elivis表达式、正则表达式、括号优先级表达式;

二、类相关表达式: 类类型表达式、类实例化、instanceof表达式、变量定义及引用、赋值表达式、自定义函数、对象属性存取及安全导航表达式、对象方法调用、Bean引用;

三、集合相关表达式: 内联List、内联数组、集合,字典访问、列表,字典,数组修改、集合投影、集合选择;不支持多维内联数组初始化;不支持内联字典定义;

四、其他表达式:模板表达式。

二、DEMO 测试:

@Testpublic void test1() {//1-首先构造一个解析器ExpressionParser parser = new SpelExpressionParser();//2-其次解析器解析字符串表达式Expression expression = parser.parseExpression("('Hello' + ' World').concat(#end)");//3- 创建上下文EvaluationContext context = new StandardEvaluationContext();//4-替换context.setVariable("end", "!");//5-求值:通过Expression接口的getValue方法,传入上下文获得表达式值。System.out.println(expression.getValue(context));}

1- parser.parseExpression("('Hello' + ' World').concat(#end)");

上面表达式拼接了 #end

2- context.setVariable("end", "!");

上下文中#end 替换为 !

输出:

Hello World!

三、ExpressionParser接口

public interface ExpressionParser {Expression parseExpression(String expressionString) throws ParseException;Expression parseExpression(String expressionString, ParserContext context) throws ParseException;
}

 Expression parseExpression(String expressionString, ParserContext context) 

传入 ParserContext  的实现类 TemplateParserContext 可以自定义解析前缀。

public interface ParserContext {//是否是模板boolean isTemplate();//模板表达式前缀String getExpressionPrefix();//模板表达式后缀String getExpressionSuffix();
}

 对上面DEMO案列更改:

@Testpublic void test1() {ExpressionParser parser = new SpelExpressionParser();//    ${ 定义解析前缀Expression expression = parser.parseExpression("HelloWorld${#end}", new TemplateParserContext("${","}") );EvaluationContext context = new StandardEvaluationContext();context.setVariable("end", "!");。System.out.println(expression.getValue(context));}

 表达式模版例子:

TemplateParserContext 解析器使用

@Test
public void test11() {//创建解析器SpelExpressionParser parser = new SpelExpressionParser();//创建解析器上下文ParserContext context = new TemplateParserContext("%{", "}");Expression expression = parser.parseExpression("你好:%{#name},我们正在学习:%{#lesson}", context);//创建表达式计算上下文EvaluationContext evaluationContext = new StandardEvaluationContext();evaluationContext.setVariable("name", "路人甲java");evaluationContext.setVariable("lesson", "spring高手系列!");//获取值String value = expression.getValue(evaluationContext, String.class);System.out.println(value);
}

四、EvaluationContext接口

表示上下文环境,默认实现是org.springframework.expression.spel.support包中的StandardEvaluationContext类,

  1. 使用setRootObject方法来设置根对象,
  2. 使用setVariable方法来注册自定义变量,
  3. 使用registerFunction来注册自定义函数等等。

五、 SPEL 语法

1-基础字面量

SpEL支持的字面量包括:字符串、数字类型(int、long、float、double)、布尔类型、null类型。

@Test
public void test2() {ExpressionParser parser = new SpelExpressionParser();String str1 = parser.parseExpression("'Hello World!'").getValue(String.class);int int1 = parser.parseExpression("1").getValue(Integer.class);long long1 = parser.parseExpression("-1L").getValue(long.class);float float1 = parser.parseExpression("1.1").getValue(Float.class);double double1 = parser.parseExpression("1.1E+2").getValue(double.class);int hex1 = parser.parseExpression("0xa").getValue(Integer.class);long hex2 = parser.parseExpression("0xaL").getValue(long.class);boolean true1 = parser.parseExpression("true").getValue(boolean.class);boolean false1 = parser.parseExpression("false").getValue(boolean.class);Object null1 = parser.parseExpression("null").getValue(Object.class);System.out.println("str1=" + str1);System.out.println("int1=" + int1);System.out.println("long1=" + long1);System.out.println("float1=" + float1);System.out.println("double1=" + double1);System.out.println("hex1=" + hex1);System.out.println("hex2=" + hex2);System.out.println("true1=" + true1);System.out.println("false1=" + false1);System.out.println("null1=" + null1);
}

输出:

str1=Hello World!
int1=1
long1=-1
float1=1.1
double1=110.0
hex1=10
hex2=10
true1=true
false1=false
null1=null
2-算数表达式:

 SpEL支持加(+)、减(-)、乘(*)、除(/)、求余(%)、幂(^)运算。

SpEL还提供求余(MOD)和除(DIV)而外两个运算符,与“%”和“/”等价,不区分大小写。

//类型示例加减乘除int result1 = parser.parseExpression("1+2-3*4/2").getValue(Integer.class);//求余
int result2 = parser.parseExpression("4%3").getValue(Integer.class);//幂运算
int result3 = parser.parseExpression("2^3").getValue(Integer.class);

 输出:

-3 
1 
8

3-关系表达式 

等于(==)、不等于(!=)、大于(>)、大于等于(>=)、小于(<)、小于等于(<=),区间(between)运算。

@Test
public void test3() {ExpressionParser parser = new SpelExpressionParser();boolean v1 = parser.parseExpression("1>2").getValue(boolean.class);boolean between1 = parser.parseExpression("1 between {1,2}").getValue(boolean.class);System.out.println("v1=" + v1);System.out.println("between1=" + between1);
}

 输出:

v1=false
between1=true
 4-逻辑表达式

且(and或者&&)、或(or或者||)、非(!或NOT)。

@Test
public void test4() {ExpressionParser parser = new SpelExpressionParser();boolean result1 = parser.parseExpression("2>1 and (!true or !false)").getValue(boolean.class);boolean result2 = parser.parseExpression("2>1 && (!true || !false)").getValue(boolean.class);boolean result3 = parser.parseExpression("2>1 and (NOT true or NOT false)").getValue(boolean.class);boolean result4 = parser.parseExpression("2>1 && (NOT true || NOT false)").getValue(boolean.class);System.out.println("result1=" + result1);System.out.println("result2=" + result2);System.out.println("result3=" + result3);System.out.println("result4=" + result4);
}

输出:

result1=true
result2=true
result3=true
result4=false
5-正则表达式

使用“str matches regex

如“”将返回true;ExpressionParser parser = new SpelExpressionParser();boolean result1 = parser.parseExpression("'123' matches '\d{3}'").getValue(boolean.class);

输出:

true

6-表达式赋值 、表达式模版

如上面标题二,就是表达式赋值

如上面标题三,表达式模版

其他调用类方法,转换类型之类不常用,可以自行查看下面知乎文档链接 

总结

  1. Spel功能还是比较强大的,可以脱离spring环境独立运行
  2. spel可以用在一些动态规则的匹配方面,比如监控系统中监控规则的动态匹配;其他的一些条件动态判断等等
  3. 本文内容比较长,建议大家把案例都敲一遍,可以设置一些断点去研究一下源码,有问题的,欢迎大家留言交流。

 本文参考 :

玩转Spring中强大的spel表达式! - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/174786047

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/317515.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Swift - 流程控制

文章目录 Swift - 流程控制if-else2. while3. for3.1 闭区间运算符3.2 半开区间运算符3.3 for - 区间运算符用在数组上3.3.1 单侧区间 3.4 区间类型3.5 带间隔的区间值 4. switch4.1 fallthrough4.2 switch注意点 5. 复合条件6. 区间匹配、元组匹配7. 值绑定8. where9. 标签语句…

【C语言】编译与链接

1.翻译环境与运行环境 在ANSI C的任何一种实现中&#xff0c;存在两个不同的环境。 1.翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令&#xff08;二进制指令&#xff09; 2.执行环境&#xff0c;它用于实际执行代码 2.翻译环境 那么翻译环境是怎么将源代码…

Java:七大基于比较的排序算法——上(思想+代码实现 超详细!)

冒泡排序、堆排序、插入排序、归并排序、快速排序、选择排序、希尔排序 目录 一、冒泡排序 1、基本思想 2、特征总结 3、代码实现 二、堆排序 1、基本思想 2、特征总结 3、代码实现 三、插入排序 1、基本思想 2、特征总结 3、代码实现 四、选择排序 1、基本思想 …

带宽的理解-笔记

带宽的理解 带宽(频带宽度)&#xff1a;是指电磁波最高频率和最低频率的差值&#xff0c;这一段频率被称为带宽。 举例说明 人耳能听到的频率范围是20赫兹到2万赫兹。换句话说&#xff0c;人而只对20赫兹至2万赫兹的声音频率有反应&#xff0c;超出或低于这一频率范围的声音我…

上市企业数字赋能指数数据集-2001到2022年(TF-IDF)

01、数据简介 上市公司数字赋能指数是一个用来衡量上市公司利用数字技术提高业务能力和效率的指标。这个指数反映了上市公司利用大数据、云计算和人工智能等数字技术&#xff0c;高效地利用商业资源和信息&#xff0c;并扩展供应关系的能力。市公司数字赋能指数是一种综合性的…

小米汽车充电枪继电器信号

继电器型号&#xff1a; 参考链接 小米SU7&#xff0c;便捷充放电枪拆解 (qq.com)https://mp.weixin.qq.com/s?__bizMzU5ODA2NDg4OQ&mid2247486086&idx1&sn0dd4e7c9f7c72d10ea1c9f506faabfcc&chksmfe48a110c93f2806f6e000f6dc6b67569f6e504220bec14654ccce7d…

基于Spring Boot的家具销售电商平台设计与实现

基于Spring Boot的家具销售电商平台设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 系统功能界面图&#xff0c;在系统首页可以查看首页…

PDF 正确指定页码后,挂载的书签页码对不上

这个问题与我的另一篇中方法一样 如何让一个大几千页的打开巨慢的 PDF 秒开-CSDN博客 https://blog.csdn.net/u013669912/article/details/138166922 另作一篇的原因 一篇文章附带一个与该文章主题不相关的问题时&#xff0c;不利于被遇到该问题的人快速搜索发现以解决其遇到…

JavaScript基础(二)

JS语法结构——引入方式 js很明显可以是一个后缀名为js的文件&#xff0c;js的引入方式和css一样&#xff0c;也有三种方式。 1.外部 使用script表现&#xff0c;只不过增加一个src属性&#xff0c;把js文件的路径src属性中。 <script src "js文件路径">&l…

查看笔记本电池容量/健康状态

1. 打开命令行提示符 快捷键“win R”后输入“cmd” 2. 在命令提示符中输入命令 “powercfg /batteryreport" 并回车 3. 查看文件 最后就可以看到笔记本的电池使用报告了

[华为OD] C卷 5G网络 现需要在某城市进行5G网络建设,已经选取N个地点设置5G基站 200

题目 现需要在某城市进行5G网络建设&#xff0c;已经选取N个地点设置5G基站&#xff0c;编号固定为1到N,接 下来需要各个基站之间使用光纤进行连接以确保基站能互联互通&#xff0c;不同基站之间架设光纤的成 本各不相同&#xff0c;且有些节点之间已经存在光纤相连&#…

mongodb使用debezium

前置 服务器上需要安装jdk11 jdk下载地址 kafka安装 官网下载地址 安装教程 debezium 安装 运行 Debezium 连接器需要 Java 11 或更高版本 Debezium 并不是一个独立的软件&#xff0c;而是很多个 Kafka 连接器的总称。这些 Kafka 连接器分别对应不同的数据库&#xff0c;…

十一、大模型-Semantic Kernel与 LangChain 的对比

Semantic Kernel 与 LangChain 的对比 Semantic Kernel 和 LangChain 都是用于开发基于大型语言模型&#xff08;LLM&#xff09;的应用程序的框架&#xff0c;但它们各有特点和优势。 基本概念和目标 Semantic Kernel 是一个由微软开发的轻量级 SDK&#xff0c;旨在帮助开发…

uniapp 自定义 App启动图

由于uniapp默认的启动界面太过普通 所以需要自定义个启动图 普通的图片不可以过不了苹果的审核 所以使用storyboard启动图 生成 storyboard 的网站&#xff1a;初雪云-提供一站式App上传发布解决方案

短视频素材哪个App最好?短视频素材哪里有免费的?

在数字媒体的黄金时代&#xff0c;富有创意的视频内容已成为吸引观众的关键。高质量的视频素材不仅能增强视觉效果&#xff0c;还能提升整体叙述的力度。以下列出了一系列全球顶尖的视频素材提供网站&#xff0c;它们将为你的广告制作、社交媒体或任何视频项目提供极具影响力的…

C++浮点数format时的舍入问题

C浮点数format时的舍入问题 首先有这样一段代码&#xff1a; #include <iostream> #include <stdio.h> using namespace std;int main() {cout << " main begin : " << endl;printf("%.0f \r\n", 1.5);printf("%.0f \r\n&…

jenkins教程

jenkins 一、简介二、下载安装三、配置jdk、maven和SSH四、部署微服务 一、简介 Jenkins是一个流行的开源自动化服务器&#xff0c;用于自动化软件开发过程中的构建、测试和部署任务。它提供了一个可扩展的插件生态系统&#xff0c;支持各种编程语言和工具。 Jenkins是一款开…

ROM修改进阶教程------如何去除安卓机型系统的开机向导 几种操作步骤解析

在和很多工作室定制化系统中。手机在第一次启动的时候系统都会进入设置向导,虽然可以设置手机的基本配置。但有很多客户需要去除手机的开机向导来缩短开机时间。确保手机直接进入工作状态。那么今天的教程针去除对开机向导的几种方法做个解析。机型很多版本不同。操作也有不同…

ENVI下遥感积雪面积信息的提取

积雪是气温、降水变化的最敏感的指示因子之一&#xff0c;ENVI为积雪面积信息的提取提供了多种技术方法 光谱统计学方法 光谱统计学提取积雪面积信息主要利用感兴趣区域ROI&#xff08;样本&#xff09;的选择&#xff0c;利用传统的监督方法实现。 决策树方法 决策树方法提取…

《HCIP-openEuler实验指导手册》1.7 Apache虚拟主机配置

知识点 配置步骤 需求 域名访问目录test1.com/home/source/test1test2.com/home/source/test2test3.com/home/source/test3 创建配置文件 touch /etc/httpd/conf.d/vhost.conf vim /etc/httpd/conf.d/vhost.conf文件内容如下 <VirtualHost *.81> ServerName test1.c…