后端——框架——容器框架——spring_core——《官网》阅读笔记——第四章节(Spring EL表达式)

  第四章节介绍Spring的EL表达式。内容大致分为两个部分

  1. 第一部分为与SpringEL相关的对象
  2. 第二部分为EL表达式。

1、核心对象

  核心对象有以下几个:

  1. ExpressionParser:EL表达式解析器,它的主要职责是解析EL表达式
  2. Expression:当解析器解析EL表达式之后,会将结果保存在该对象中,调用对象的getValue方法获取解析的结果。
  3. EvaluationContext:解析的上下文,当EL表达式中存在变量,属性,方法时,根据上下文解析这些变量和方法。当为上下文中的变量时,当为JVM属性或者是容器中存在的properties属性时,当为容器中某个Bean的字段时,当为容器中对象的方法时,都会去上下文中查询相应的变量。如果只解析字面量,基本上用不到。
  4. SpelParserConfiguration:TODO,待补充。

2、EL表达式

  我把EL表达式分为以下四类,

  1. 表达式为XX expression
  2. 运算符为XX operator
  3. 集合为Map,List,数组等相关的操作。
  4. 方法为调用构造器,调用类方法

2.1 表达式

  表达式为XX expression,例如Literal expression,赋值,访问属性等表达式。

2.1.1  字面量

  字面量有字符串,数字,布尔,null。

/**
 * 
 * @Title: testLiteralExpression
 * @Description: 测试SpringEL表达式
 */
public static void testLiteralExpression() {
	// 创建解析器
	ExpressionParser parser = new SpelExpressionParser();
	// 表达式
	Expression exp = parser.parseExpression("'Hello World'");
	// 字符串
	String helloWorld = exp.getValue(String.class);
	// 获取数字
	exp = parser.parseExpression("123");
	// 数字
	Integer num = exp.getValue(Integer.class);
	// 布尔值
	boolean blValue = parser.parseExpression("true").getValue(Boolean.class);
	// null
	Object nullVal = parser.parseExpression("null").getValue();
	System.out.println("HelloWorld:" + helloWorld + "
num:" + num + "
blValue:" + blValue + "
nullVal:" + nullVal);
}

2.1.2  Bean属性

  当获取对象的属性时,需要在上下文中明确对象,体现在代码上,getValue的第二个参数为对象的实例。

  例如获取User的name属性

/**
 * 
 * @Title: testBeanFields  
 * @Description: 测试获取bean的属性
 */
public static void testBeanFields() {
	// 创建解析器
	ExpressionParser parser = new SpelExpressionParser();
	// 表达式
	Expression exp = parser.parseExpression("name");
	// 创建User对象
	User user = new User();
	user.setName("张三");
	// 获取name属性,第一个参数为对象的实例,第二个参数为name属性的类型
	String name = exp.getValue(user, String.class);
	System.out.println("name:" + name);
}

  当属性为对象时,例如User有Address(地址)属性,address.country,表示用户所在的国家,即Address对象中的country属性。

  当属性为集合,数组时,例如User有List<Role>属性,roles[index]访问到Role对象,roles[index].name获取Role对象的角色名称。

  当属性为Map时,其中的index转换为key。

2.1.3   系统属性

  系统属性是指JVM属性和操作系统的属性。获取系统属性的格式为:#{systemProperties[key]}

  其中

  • #:表示变量
  • {}:变量包裹在大括号中
  • systemProperties:它代表系统属性。
  • key:系统属性变量的key值。

  例如获取user.name系统变量 

public class User {
	// 用户的名称
	@Value("#{ systemProperties['user.name'] }")
	private String name;
	// 其他代码省略
}

  当从IOC容器中获取时,name的属性值会是user.name系统变量值。使用new方式自定义User对象时,name属性无值。

  表达式也可以出现在XML配置文件中,当使用property子标签设置name属性时,当value为表达式的值时,也会被解析为user.name系统变量值。

2.1.4   表达式模板

  表达式模板是指引用上下文中对象的属性,调用上下文中对象的方法,获取它返回值等等。

// 任意的表达式模板,必须把User设置为上下文对象,并且User的name属性有值
Expression exp = parser.parseExpression("your name is #{name} ");

  返回字符串“your name is 张三”。

2.2 运算符

  运算符有五种,关系运算符,逻辑运算符,算术运算符,赋值运算符,三目运算符。

2.2.1  关系运算符

  关系运算符,大于,等于,小于等等,这些值返回的都是布尔类型。

/**
 * 
 * @Title: testRelationalOperators
 * @Description: 测试关系运算符
 */
public static void testRelationalOperators() {
	// 创建解析器
	ExpressionParser parser = new SpelExpressionParser();
	// 任意的关系运算符
	Expression exp = parser.parseExpression("1 < 2");
	// 获取值
	Boolean isTrue = exp.getValue(Boolean.class);
	// 关系运算符
	System.out.println("relational expression:" + isTrue);
}

2.2.2   逻辑运算符

  逻辑运算符有与,或,非三种,Spel使用and,or,not表示。返回的值也都是布尔类型

// 任意的逻辑运算符
Expression exp = parser.parseExpression("true and false");

2.2.3   算术运算符

  算术运算符有加,减,乘,除,余,各种函数等。返回的基本都是数字类型

// 任意的算术运算符
Expression exp = parser.parseExpression("1 + 1");

2.2.4   赋值运算符

  赋值运算符有=,+=,-=等等。

// 任意的赋值运算符,value是字符串,需要加单引号
Expression exp = parser.parseExpression(" key=’value’ ");

  还可以调用expression的setValue方法。

// 任意的赋值运算符,field是某个对象的属性 
Expression exp = parser.parseExpression(" field ");
// setValue方法,第一个参数为上下文对象,第二个参数为对象实例,第三个为filed属性的值
exp.setValue(context, inventor, "fieldVal");

2.2.5  三目运算符

  格式与Java程序中的三目运算符一致。

  exp ? ‘true value’ :’false value’。

// 任意的三目表达式,值是字符串,需要添加单引号
Expression exp = parser.parseExpression(" true ? 'true value' : 'false value' ");

2.2.6  Elvis 运算符

  它是三目运算符的缩写,是Groovy语言的语法。

  表达式一般是判断对象或字段是否为空,true value 一般是对象或字段本身,false value一般是对象或字段的默认值。

  格式为: obj ? new Object() 或 field ? “default field Value”;

// 任意的Elvis运算符,相当于name属性无值时,给其设置默认值张三
Expression exp = parser.parseExpression(" name ? : '张三' ");

2.2.7   Safe navigation运算符

  它是在获取对象的属性时,添加一层机制,确保即使对象为空时,也不会抛出空指针异常,相当于获取对象属性的加强版。

  格式为:obj ?. field。 中间是问号和逗号,二者之间无空格。  

// 任意的获取属性的运算符,获取User对象中的address对象,address对象中的country属性值
Expression exp = parser.parseExpression(" address?.country ");

2.3 集合

  集合这里指存放数据的容器,指数组,Collection,Map。

2.3.1  创建

  1. List集合:格式为{value1,value2,value3},大括号可以互相嵌套。返回List对象
// {value1,value2,value3}等格式,大括号可以互相嵌套
Expression exp = parser.parseExpression("{1,2,3,4}");

  2.Map:格式为{key:’value’},相当于JSON字符串。Key值没有单引号,value上有单引号

// 获取时返回Map对象
Expression exp = parser.parseExpression("{name:'张三', age:18}");

  3.数组:格式为Java创建数组的格式,new type[length]

// 创建int数组,大小为4,前两个的值为1,2,后面两个使用默认值0
Expression exp1 = parser.parseExpression("new int[4]{1,2}");

2.3.2  遍历

  遍历集合的格式为 coll.?[boolean exp],相当于JS数组的filter方法。其中

  1. Coll:表示遍历的集合
  2. .?:逗号和问号为固定格式。
  3. Exp:将当前遍历的对象作为上下文,编写过滤条件,例如[name == ‘张三’],遍历用户的集合,返回姓名为张三的用户。

  当为map类型时,方括号内部使用key表示当前遍历到的键值,使用value表示当前遍历到的value值。

  当只想获取集合中满足条件的第一个值时,coll.^[Boolean exp],

  当只想获取集合中满足条件的最后一个值是,coll.$[Boolean exp]。

2.3.3   投影

  集合投影的格式为coll.![projection expression],相当于JS数组的map方法。其中

  1. Coll:表示遍历的集合
  2. .! :逗号和感叹号为固定格式。
  3. Projection expression:将当前遍历的对象作为上下文,编写投影的表达式,例如[‘test’ + name],遍历当前用户,返回当前用户的用户名集合,并且在每个用户名上添加test前缀。

2.3.4  引用上下文

  无论是上述提到的遍历,投影操作,都可以通过 #this引用到当前遍历的对象,通过#root访问到上下文对象,例如Role对象有List<User>,那么#root会引用到role对象,#this会引用到当前遍历的User对象。

2.4 方法

2.4.1   构造器

  在Spel中调用构造器,需要new classFullName,即类全名(包名+类名)。

2.4.2   对象方法

  在Spel中调用对象方法时,必须将对象添加到上下文中。

// 调用User对象的getName方法,返回'your name is 张三'
Expression exp = parser.parseExpression("your name is getName()"); 
原文地址:https://www.cnblogs.com/rain144576/p/12272416.html