• 后端——框架——容器框架——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()"); 
  • 相关阅读:
    JAVA整理05---手写简单的linkedlist来学习linkedlist
    JAVA整理04---手写简单的arraylist来学习arraylist
    java整理03--常用类
    java整理02--面向对象深入
    每周学习进度
    软件工程课程总结
    梦断代码阅读笔记03
    scrum第二阶段项目冲刺_day10
    scrum第二阶段项目冲刺_day09
    scrum第二阶段项目冲刺_day08
  • 原文地址:https://www.cnblogs.com/rain144576/p/12272416.html
Copyright © 2020-2023  润新知