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'}" />
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>
"manager" class="com.stream.spring.spel.entity.Manager">
"employees" value="#{employees[3]}"/>
Result:
manager.employees.size() = 1;
manager.employees.get(0).getName = "employee4";
"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";
id="manager" class="com.stream.spring.spel.entity.Manager">
<property name="employee" value="#{employees.^[age ge 23]}"/>
Result:
mananer.employee.name = "employee3";
id="manager" class="com.stream.spring.spel.entity.Manager">
<property name="employee" value="#{employees.$[age ge 23]}"/>
Result:
mananer.employee.name = "employee6";
"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";