SPEL(Spring Expression Language)即Spring3中功能丰富强大的表达式语言,简称SpEL。SpEL是类似于OGNL和JSF EL的表达式语言,能够在运行时构建复杂表达式,存取对象属性、对象方法调用等。所有的SpEL都支持XML和Annotation两种方式,格式:#{ SpEL expression }。
可参考文章
CSDN博主 gudong2945 的《Spring 表达式语言 (Spring Expression Language) SpEL》
Spring官方文档 第9章 Spring Expression Language (SpEL)
Spring SPEL功能简介
通过spel我们可以实现
1. 通过bean的id对bean进行引用
1. 调用方法以及引用对象中的属性
1. 计算表达式的值
1. 正则表达式的匹配
1. 集合的操作
Spring SPEL配置
Maven依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.1.RELEASE</version>
</dependency>
只需要将spring-context添加到依赖即可,spring-context中有对spring-expression的依赖,添加依赖后会自动下载。
Spring配置文件中的配置
增加对P标签和Util的支持,修改schema,添加P和Util
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
<!--xsi:schemaLocation中增加-->
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
最终结果如下
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
</beans>
注入基础类型
<property name="name" value="#{'jaune'}" /> <!--字符串注入,一定要带单引号,如果不带单引号,表示注入的是Bean。也可以用下面的方式-->
<property name="name" value='#{"jaune"}' />
<property name="age" value="#{15}" /> <!--整型-->
<property name="money" value="#{58.6}" /> <!-- 浮点型 -->
<property name="money" value="#{1e4}" /> <!-- 浮点型,科学计数法 -->
<property name="is" value="#{true}" /> <!-- 布尔类型 -->
引用对象、属性和方法
对象引用
语法如下:#{beanId}
<bean id="people" class="com.codestd.springstudy.lesson03.People" />
...
<property name="people" value="#{people}" />
<!--等同于使用ref-->
<property name="people" ref="people" />
对象属性引用
语法如下:#{beanId.propertyName}
<bean id="people" class="com.codestd.springstudy.lesson03.People">
<property name="name" value="jaune" />
</bean>
...
<property name="name" value="#{people.name}" />
对象方法引用
语法如下:#{beanId.method()}
<bean id="people" class="com.codestd.springstudy.lesson03.People">
<property name="name" value="jaune" />
</bean>
...
<property name="name" value="#{people.getName()}" />
还可以链式操作
<property name="name" value="#{people.getName().toUpperCase()}" />
这样写如果people.getName()为null,会抛出空指针异常,为了避免抛出异常我们要使用?.表达式
<property name="name" value="#{people.getName()?.toUpperCase()}" />
调用类的静态方法
语法:T(class.method())
<property name="pi" value="#{T(java.lang.Math).PI}" />
SPEL运算符支持
算术运算符
算数运算符:+, -, *, /, %, ^
语法:#{number+number}
#{number-number}
···
<property name="number" value="#{15 + 3}" /> <!-- 18 -->
<property name="number" value="#{15 - 3}" /> <!-- 12 -->
<property name="number" value="#{15 * 3}" /> <!-- 45 -->
<property name="number" value="#{15 / 3}" /> <!-- 5 -->
<property name="number" value="#{15 % 3}" /> <!-- 0 -->
<property name="number" value="#{2 ^ 2}" /> <!-- 4 -->
字符串连接
字符串连接符:+
语法:#{'str1' + 'str2'}
<property name="name" value="#{'wang' + 'chengwei'}" /> <!-- wangchengwei -->
<property name="name" value="#{people.name + 'chengwei'" />
比较运算符
比较运算符: <, >, ==, <=, >=, lt(<), gt(>), eq(==), le(<=), ge(>=)
注意在XML中不能使用
>
和>=
需要用gt
和ge
代替,<
和<=
亲测可用
<property name="is" value="#{1>2}" /> <!-- false -->
...
逻辑运算符
逻辑运算符号:and, or, not, !
<property name="is" value="#{true and true}" /> <!-- true -->
<property name="is" value="#{true or false}" /> <!-- true -->
<property name="is" value="#{not true}" /> <!-- false -->
<property name="is" value="#{!true}" /> <!-- false -->
if…else表达式
基本语法:条件?true:false
<bean id="people" class="com.codestd.springstudy.lesson03.People">
<!-- <property name="name" value="jaune" /> -->
</bean>
<property name="name" value="#{people.name != null ? people.name :' wangchengwei'}" />
#wangchengwei
更为简洁的方式
<property name="name" value="#{people.name ?:' wangchengwei'}" />
#wangchengwei
注意:
?:
之间不能有空格
正则表达式
使用matches
关键字,结果为布尔类型
<property name="is" value="#{people.name matches '[a-zA-Z]{2,10}'}" />
SPEL对集合的支持
定义Bean实体类
package com.codestd.springstudy.lesson03;
import org.springframework.stereotype.Component;
public class People {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
List集合
定义集合
<util:list id="peopleList">
<bean class="com.codestd.springstudy.lesson03.People" p:name="jaune001" />
<bean class="com.codestd.springstudy.lesson03.People" p:name="jaune002" />
<bean class="com.codestd.springstudy.lesson03.People" p:name="jaune003" />
<bean class="com.codestd.springstudy.lesson03.People" p:name="jaune004" />
</util:list>
其中p:name="jaune003"
等同于<property name="name" value="jaune003" />
通过下标访问集合中的元素
<property name="people" value="#{peopleList[0]}" />
<property name="name" value="#{peopleList[0].getName()}" />
从Map中获取指定的Key
定义Map集合
<util:map id="peopleMap">
<entry key="jaune001">
<bean class="com.codestd.springstudy.lesson03.People" p:name="jaune001" />
</entry>
<entry key="jaune002">
<bean class="com.codestd.springstudy.lesson03.People" p:name="jaune001" />
</entry>
</util:map>
通过key访问集合中的元素
<property name="people" value="#{peopleMap['jaune001']}" />
<property name="name" value="#{peopleMap['jaune001'].getName()}" />
从Properties中获取制定的Key
添加Properties文件,文件位置放到spel/setup.properties
,文件内容如下
system.name=spel
Properties文件的使用
<util:properties id="setup" location="classpath:spel/setup.properties" />
...
<property name="name" value="#{setup['system.name']}" />
通过下标访问systemEnvironment(系统环境变量)和systemProperties(系统属性)中的值
<property name="name" value="#{systemEnvironment['JAVA_HOME']}" />
<property name="name" value="#{systemProperties['java.version']}" />
在JDK文档中System类中有这样的方法getProperties()在此方法的详细介绍中有下面的参数可供使用:
java.version Java 运行时环境版本
java.vendor Java 运行时环境供应商
java.vendor.url Java 供应商的 URL
java.home Java 安装目录
java.vm.specification.version Java 虚拟机规范版本
java.vm.specification.vendor Java 虚拟机规范供应
java.vm.specification.name Java 虚拟机规范名称
java.vm.version Java 虚拟机实现版本
java.vm.vendor Java 虚拟机实现供应商
java.vm.name Java 虚拟机实现名称
java.specification.version Java 运行时环境规范版本
java.specification.vendor Java 运行时环境规范供应商
java.specification.name Java 运行时环境规范名称
java.class.version Java 类格式版本号
java.class.path Java 类路径
java.library.path 加载库时搜索的路径列表
java.io.tmpdir 默认的临时文件路径
java.compiler 要使用的 JIT 编译器的名称
java.ext.dirs 一个或多个扩展目录的路径
os.name 操作系统的名称
os.arch 操作系统的架构
os.version 操作系统的版本
file.separator 文件分隔符(在 UNIX 系统中是“/”)
path.separator 路径分隔符(在 UNIX 系统中是“:”)
line.separator 行分隔符(在 UNIX 系统中是“/n”)
user.name 用户的账户名称
user.home 用户的主目录
user.dir 用户的当前工作目录
获取字符串中的某个字符
可直接通过下标获取字符串中的某个字符
<property name="name" value="#{systemProperties['java.version'][0]}" />
条件筛选
筛选子集
<property name="people" value="#{peopleList.?[name == 'jaune004'][0]}" />
<!--表示取第一个-->
<property name="people" value="#{peopleList.^[name == 'jaune004']}" />
<!--表示取最后一个-->
<property name="people" value="#{peopleList.$[name == 'jaune004']}" />
peopleList.?[name == 'jaune004']
筛选出的是一个List集合,后面加上下标表示取第1个。
注意:这种写法在无法匹配到元素时会报错
集合的投影
语法:.![]
,集合返回的是集合,在Bean中先添加集合属性
private List<String> names;
<property name="names" value="#{peopleList.![name]}"></property>
返回:names[jaune001, jaune002, jaune003, jaune004]