文章目录
Spring SpEL表达式
简单使用
导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.20</version>
<scope>compile</scope>
</dependency>
简单解析并使用
public class test {
public static void main(String[] args) {
//spel解析器
SpelExpressionParser spel = new SpelExpressionParser();
//解析spel表达式 返回Expression 对象(计算)
Expression exp = spel.parseExpression("'Hello'.toUpperCase()");
//获取值
String value = exp.getValue(String.class);
System.out.println(value);//输出HELLO
}
}
关于对象的简单使用(修改对象的属性)
public class test {
public static void main(String[] args) {
User user = new User();
user.setName("ck");
user.setAge(18);
SpelExpressionParser spel = new SpelExpressionParser();
//多了EvaluationContext 接口
EvaluationContext standardEvaluationContext = new StandardEvaluationContext(user);
spel.parseExpression("age").setValue(standardEvaluationContext, 55);
System.out.println(user.getAge());
}
}
SpEL编译器
重复编译的设定
如果相同的表达式多次使用,每次都要解析浪费资源。可以设置让经常使用的转换为字节码。
SpelParserConfiguration spelParserConfiguration = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, test.class.getClassLoader());
SpelExpressionParser spelExpressionParser = new SpelExpressionParser(spelParserConfiguration);
-
IMMEDIATE 立即启动编译,在第二次表达式取值时才会启用编译
-
OFF 默认,不启动编译
-
MIXED 混合型 在解释形和编译型互相切换 在解释了一定数量后(100),变成编译形
SpEL基础表达式
文本字符解析
支持字符串,日期,数字,布尔,null
字符串用单引号包住或者 "包住,单引号字符’
public class test {
public static void main(String[] args) {
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
String value = (String)spelExpressionParser.parseExpression("'hello'").getValue();
Double value1 = (Double)spelExpressionParser.parseExpression("6.2333E+4").getValue();
int value2 = (Integer)spelExpressionParser.parseExpression("0x7FFFFFFF").getValue();
boolean value3 = (Boolean)spelExpressionParser.parseExpression("true").getValue();
Object value4 = spelExpressionParser.parseExpression("null").getValue();
}
}
对象属性解析
public class test {
public static void main(String[] args) {
User user = new User();
user.setName("陈克");
user.setAge(18);
user.setPlaceOfBirsth(new placeOfBirsth("中国","福州"));
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext(user);
//基本属性值获取
String name = (String)parser.parseExpression("name").getValue(context);
Integer age = (Integer)parser.parseExpression("age + 10").getValue(context);
System.out.println(name);//陈克
System.out.println(age);//28
//嵌套对象属性值获取
String city = (String)parser.parseExpression("placeOfBirsth.city").getValue(context);
System.out.println(city);//中国
}
}
数组,集合形式解析
不支持多维数组的初始化
public class test {
public static void main(String[] args) {
User user = new User();
user.setName("陈克");
user.setAge(18);
user.setPlaceOfBirsth(new placeOfBirsth("中国","福州"));
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext(user);
//一维数组的 创建和初始化
int[] array = (int[])parser.parseExpression("new int[]{1,2,3}").getValue(context);
//多维数组的创建
int[][] array1 = (int[][])parser.parseExpression("new int[2][3]").getValue();
//List
List list = (List)parser.parseExpression("{1,2,3,4}").getValue();
//Liat中List
List list1 = (List)parser.parseExpression("{{'a','b'},{'x','y'}}").getValue();
//Map
Map map = (Map)parser.parseExpression("{userName:'tom',credite:100}").getValue();
//list中的Map
List list3 = (List)parser.parseExpression("{{userName:'tom',credite:100},{userName:'tom1',credite:200}}").getValue();
//map中的List
Map map1 = (Map)parser.parseExpression("{userName:{'a','b'},credite:{'c','d'}}").getValue();
//从数组,list,map中取出值(从对象中取出 ints为实体类的变量名)
int value = (Integer)parser.parseExpression("ints[0]").getValue(context);
String list = (String)parser.parseExpression("list[0]").getValue(context);
String map = (String)parser.parseExpression("map['name']").getValue(context);
}
}
方法解析
可以调用对象所有的可用的实例方法。静态方法。可变参方法
实体类
@Data
public class User {
private String name;
private Integer age;
private placeOfBirsth placeOfBirsth;
private List list;
private int[] ints;
private Map map;
public static void say(String mes)
{
System.out.println(mes);
}
public void sleep(String mes,String... args)
{
System.out.println(mes + Arrays.toString(args));
}
}
使用
public class test {
public static void main(String[] args) {
User user = new User();
user.setName("陈克");
user.setAge(18);
user.setPlaceOfBirsth(new placeOfBirsth("中国","福州"));
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext(user);
//调用实例方法
String name = parser.parseExpression("getName()").getValue(context,String.class);
//调用静态方法
String say = parser.parseExpression("say('我说')").getValue(context,String.class);
//调用可变参方法
String sleep = parser.parseExpression("sleep('我说','2','2')").getValue(context,String.class);
}
}
关系操作符
public class test1 {
public static void main(String[] args) {
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
//关系操作符
Boolean value = spelExpressionParser.parseExpression("2==2").getValue(Boolean.class);
Boolean value1 = spelExpressionParser.parseExpression("2>5").getValue(Boolean.class);
//string比较(不支持 但是spel支持)
Boolean value2 = spelExpressionParser.parseExpression("'不'>'持'").getValue(Boolean.class);
//instanceof
Boolean value3 = spelExpressionParser.parseExpression("'不' instanceof T(String)").getValue(Boolean.class);
//正则表达式
Boolean value4 = spelExpressionParser.parseExpression(" '8' matches '^[1-9]d*$'").getValue(Boolean.class);
System.out.println(value4);
}
}
逻辑操作符
- 与操作(&& 或者 and)
- 或操作(|| 或者 or)
- 非(!)
public class test1 {
public static void main(String[] args) {
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
//逻辑操作符
Boolean value = spelExpressionParser.parseExpression("true and false").getValue(Boolean.class);
Boolean value1 = spelExpressionParser.parseExpression("true && false").getValue(Boolean.class);
Boolean value2 = spelExpressionParser.parseExpression("true || false").getValue(Boolean.class);
Boolean value3 = spelExpressionParser.parseExpression("true or false").getValue(Boolean.class);
Boolean value4 = spelExpressionParser.parseExpression("!true").getValue(Boolean.class);
System.out.println(value4);
}
}
算术运算符
public class test1 {
public static void main(String[] args) {
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
//逻辑操作符
Integer value = spelExpressionParser.parseExpression("1 + 1").getValue(Integer.class); //1
Integer value1 = spelExpressionParser.parseExpression("3 * 5.658").getValue(Integer.class); //16
Integer value2 = spelExpressionParser.parseExpression("10 / 3").getValue(Integer.class); //3
Integer value3 = spelExpressionParser.parseExpression("10 % 3").getValue(Integer.class); //1
Integer value4 = spelExpressionParser.parseExpression("10^3 ").getValue(Integer.class); //1000
}
}
安全导航符
类似java8 的 Optional
用?号来判断对象是否为null。为null就返回字符串null,而不是空指针
public class test1 {
public static void main(String[] args) {
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
User user = new User();
user.setName("ck");
user.setAge(15);
// user.setBody(new Body("bp","bt"));
StandardEvaluationContext context = new StandardEvaluationContext(user);
//逻辑操作符
String value = spelExpressionParser.parseExpression("body?.hand").getValue(context,String.class);
System.out.println(value);
}
}
三元操作符
Integer value = spelExpressionParser.parseExpression("name == 'ck'? age+10:age").getValue(context,Integer.class);
Elvis操作符
三元表达式类似的简写
如果name不为null则取原来的值,如果为null取value
String value = spelExpressionParser.parseExpression("name?:'名字为空'").getValue(context,String.class);
赋值,类型,构造器,变量
赋值
public class test {
public static void main(String[] args) {
User user = new User();
user.setName("陈克");
user.setAge(18);
user.setPlaceOfBirsth(new placeOfBirsth("中国","福州"));
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext(user);
//修改user的age值 方式一
parser.parseExpression("age").setValue(context,55);
//修改user的age值 方式二
parser.parseExpression("age = 66").getValue(context);
}
}
类型
T(全限定类名),如果在java.lang包下可以不写包名
public class test {
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
//获得对应的class对象
Class value = parser.parseExpression("T(String)").getValue(Class.class);
Class value1 = parser.parseExpression("T(com.ke.spel.User)").getValue(Class.class);
//可以直接调用静态方法
String value2 = parser.parseExpression("T(com.ke.spel.User).say('你干嘛')").getValue(String.class);
}
}
构造器
用new关键字,除了基本类型和String,其他都要用全限定类名
public class test {
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
User value = parser.parseExpression("new com.ke.spel.User()").getValue(User.class);
System.out.println(value);
}
}
变量
public class test {
public static void main(String[] args) {
User user = new User();
user.setName("ck");
user.setAge(18);
EvaluationContext context = new StandardEvaluationContext(user);
//把变量存在EvaluationContext(其中维护着一个map)对象中
context.setVariable("newName","cxk");
SpelExpressionParser parser = new SpelExpressionParser();
parser.parseExpression("name=#newName").getValue(context);
System.out.println(user.getName());
}
}
集合过滤
public class test {
public static void main(String[] args) {
User user = new User();
user.setName("ck");
user.setAge(18);
EvaluationContext context = new StandardEvaluationContext(user);
//存入List
ArrayList<Integer> integers = new ArrayList<>();
integers.addAll(Arrays.asList(50,100,150,200,250,300,350));
context.setVariable("list",integers);
//存入Map
HashMap map = new HashMap<>();
map.put("ck",20);
map.put("cyz",30);
map.put("cxk",40);
map.put("gs",50);
context.setVariable("map",map);
SpelExpressionParser parser = new SpelExpressionParser();
//从list找出大于200的元素(this前有#号)
ArrayList<Integer> value = (ArrayList<Integer>)parser.parseExpression("#list.?[#this>200]").getValue(context);
//从map找value大于30的元素(value前没有#号)
Map value1 = (Map)parser.parseExpression("#map.?[value>30]").getValue(context);
//从map找value大于30的元素(value前没有#号)(^代表取出符合条件的第一个)
Map value2 = (Map)parser.parseExpression("#map.^[value>30]").getValue(context);
//从map找value大于30的元素(value前没有#号)($代表取出符合条件的最后一个)
Map value3 = (Map)parser.parseExpression("#map.$[value>30]").getValue(context);
//根据条件转换并返回对应 List(!符号)
//[60, 70, 50, 80]
ArrayList<Integer> value4 = (ArrayList<Integer>)parser.parseExpression("#map.![value+30]").getValue(context);
//[250, 300, 350, 400, 450, 500, 550]
ArrayList<Integer> value5 = (ArrayList<Integer>)parser.parseExpression("#list.![#this+200]").getValue(context);
//[false, true, false, true]
ArrayList<Integer> value6 = (ArrayList<Integer>)parser.parseExpression("#map.![value>30]").getValue(context);
//[false, false, false, false, true, true, true]
ArrayList<Integer> value7 = (ArrayList<Integer>)parser.parseExpression("#list.![#this>200]").getValue(context);
}
}
Spring使用Spel表达式
基于XML配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="hello" class="springEl.Mes"
p:mes="#{systemProperties['java.class.path']}"
p:mes1="#{systemProperties['os.name']}"
p:mes2="#{ T(Double).toString(T(Math).random())}"
p:mes3="#{ hello2.mes }"
/>
<bean id="hello2" class="springEl.Mes"
p:mes="你好"
/>
</beans>
systemProperties可以获得系统参数,也可以调用静态方法,也可以直接引用其他bean的值
public class test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beansEl.xml");
Mes bean = (Mes)applicationContext.getBean("hello");
//获取java环境变量
System.out.println(bean.getMes());
//获取操作系统版本 Windows 10
System.out.println(bean.getMes1());
//自定义设置的值0.5541974835747724
System.out.println(bean.getMes2());
//你好
System.out.println(bean.getMes3());
}
}
注解配置
配置文件peizhi.properties
username = ck
password = 666666
div = a.b.c.d
spring配置文件设置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!--扫描springEl包下的注解-->
<context:component-scan base-package="springEl"/>
<!--读取配置文件-->
<util:properties id="properties" location="classpath:peizhi.properties"/>
<!--配置可简写spel设置-->
<context:property-placeholder properties-ref="properties"/>
</beans>
配置直接写入数据
@Component
@Data
public class config {
@Value("#{properties['username']}")
private String userName;
@Value("#{properties['password']}")
private String passWord;
@Value("${div}")
private String div;
}
在配置了spel简写后可以用${字段名}来简化