Spring之SpEL

前言

Spring3引入了Spring表达式语言(SpEL),可以像jsp中的el表达式一样,在运行期动态执行,从而得到需要的值。
SpEL的特性包括:
- 使用Bean的ID来引用Bean
- 调用方法和访问对象的属性
- 对值进行算术、关系和逻辑运算
- 正则表达式匹配
- 集合操作

字面值

字面值是最简单的SpEL表达式。一个简单的SpEL表达式如下:

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="age" value="#{5}" />

#{}符号标记该内容为SpEL表达式。
浮点型数字也可以出现在SpEL表达式中:

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="age" value="#{5.2}" />

还可以使用科学计数法:

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="age" value="#{1e4}" />

age = 10000.0;

还可以true或者false:

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="married" value="#{false}"/>

String类型的字面值可以使用单引号或者双引号作为字符串的界定符:

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="managerName" value="#{'Stream'}" />

引用Bean、Properties和方法

SpEL的另外一个基本应用是使用ID来引用其它Bean。

id="manager" class="com.stream.spring.spel.entity.Manager">
    <property name="name" value="Stream"/>

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="managerName" value="#{manager.name}" />

还可以调用Bean中的方法:

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="managerName" value="#{manager.getManagerName()}" />

将名字变为小写:

id="employee" class="com.stream.spring.spel.entity.Employee">
   <property name="managerName" value="#{manager.getManagerName().toLowerCase()}" />

上面的调用方式中,如果getManagerName()返回null,那么将会报错:

org.springframework.expression.spel.SpelEvaluationException: EL1011E:(pos 25): Method call: Attempted to call method toLowerCase() on null context object

为了避免null值的出现导致错误,可以用(?.)代替(.),这样当出现null时将忽略后面的操作。
对于字符串,可以使用[]根据索引取到相应的结果:

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="managerName" value="#{T(com.stream.spring.util.StringUtil).toString('Streamwei')[3]}" />

employee.managerName = "e";

注意索引是从0开始。

操作类

SpEL还能调用类的静态方法和和常量,使用T()运算符即可。

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="managerName" value="#{T(com.stream.spring.util.ConstUtil).MANAGER}" />

如上面的代码,在com.stream.spring.util.ConstUtil中定义了一个常量,T(com.stream.spring.util.ConstUtil)返回ConstUtil的一个实例,然后取到该实例的MANAGER字段。静态方法一样的道理:

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="managerName" value="#{T(com.stream.spring.util.StringUtil).toString('Streamwei')}" />

算术运算和逻辑运算

SpEL提供了多种运算符来操作表达式。

运算符类型 运算符
算术运算符 +、-、*、/、%、^(乘方运算)
关系运算符 <(lt)、>(gt)、==(eq)、<=(le)、>=(ge)
逻辑符类型 and、or、not、!
条件运算 ?A:B
正则表达式 matches

算术运算符中,除了+之外,其余的要求参与运算的都是数字。+的两边可以是字符串,这时候执行字符串合并的操作。操作数既可以是字面量,也可以是用SpEL求到的值。

<bean id="employee" class="com.stream.spring.spel.entity.Employee">
     <property name="age" value="#{30}"/>
     
     <property name="married" value="#{employee2.age ge 27 ? true : false}" />
 bean>

matches运算符有两个操作数,左边的参数是要检测的字符串,右边的参数是正则表达式,如果字符串匹配正则表达式返回true,否则返回false。

id="employee" class="com.stream.spring.spel.entity.Employee">
    <property name="age" value="#{30}"/>
    <property name="married" value="#{employee2.age matches '[0-9.]+'}" />

employee.married = true

操作集合

SpEL主要用三个运算符来操作集合:

运算符 返回值
.?[] 根据条件在给定集合中查询元素,并返回一个由查询出的元素组成的新集合
.^[]、.$[] 从给定集合中查询第一个、最后一个元素,返回集合中的元素
.![] 从集合的每一个成员中选择指定的属性,返回一个新的集合,新的集合类型和原有集合不一定相同

首先定义一个list:

list id="employees">
    id="employee1" class="com.stream.spring.spel.entity.Employee">
        <property name="name" value="employee1"/>
        <property name="age" value="21"/>
    
    id="employee2" class="com.stream.spring.spel.entity.Employee">
        <property name="name" value="employee2"/>
        <property name="age" value="22"/>
    
    id="employee3" class="com.stream.spring.spel.entity.Employee">
        <property name="name" value="employee3"/>
        <property name="age" value="23"/>
    
    id="employee4" class="com.stream.spring.spel.entity.Employee">
        <property name="name" value="employee4"/>
        <property name="age" value="24"/>
    
    id="employee5" class="com.stream.spring.spel.entity.Employee">
        <property name="name" value="employee5"/>
        <property name="age" value="25"/>
    
    id="employee6" class="com.stream.spring.spel.entity.Employee">
        <property name="name" value="employee6"/>
        <property name="age" value="26"/>
    
list>
  1. 用[]来获取集合
"manager" class="com.stream.spring.spel.entity.Manager">
    "employees" value="#{employees[3]}"/>

Result:
manager.employees.size() = 1;
manager.employees.get(0).getName = "employee4";
  1. 使用.?[]筛选出age>=23的记录
"manager" class="com.stream.spring.spel.entity.Manager">
    "employees" value="#{employees.?[age ge 23]}"/>

Result:
manager.employees.size() = 4;
manager.employees.get(0).getName = "employee3";
  1. 使用.^[]筛选出age>=23的记录的第一个元素
id="manager" class="com.stream.spring.spel.entity.Manager">
    <property name="employee" value="#{employees.^[age ge 23]}"/>

Result:
mananer.employee.name = "employee3";
  1. 使用.$[]筛选出age>=23的记录的最后一个元素
id="manager" class="com.stream.spring.spel.entity.Manager">
    <property name="employee" value="#{employees.$[age ge 23]}"/>

Result:
mananer.employee.name = "employee6";
  1. 使用.![]讲age>=23的元素的name抽取出来形成一个List
"manager" class="com.stream.spring.spel.entity.Manager">
    "employeesName" value="#{employees.?[age ge 23].![name]}"/>

Result:
manager.employeesName.size = 4;
manager.employeesName.get(0) = "employee3";
manager.employeesName.get(1) = "employee4";
manager.employeesName.get(2) = "employee5";
manager.employeesName.get(3) = "employee6";

注意.![]的筛选条件,不能写成[‘name’],否则会把’name’作为一个字符串:

"manager" class="com.stream.spring.spel.entity.Manager">
    "employeesName" value="#{employees.?[age ge 23].![name]}"/>

Result:
manager.employeesName.size = 4;
manager.employeesName.get(0) = "name";
manager.employeesName.get(1) = "name";
manager.employeesName.get(2) = "name";
manager.employeesName.get(3) = "name";

你可能感兴趣的:(spring,spring,spel)