Spring中的SpEL
2016-03-12 22:23
519 查看
Spring表达式语言(简称SpEL)是一种与JSP 2 EL功能类似的表达式语言,他可以在运行时查询和操作对象图。还支持方法调用和基本字符串模板函数。
SpEL可以独立于SPring容器使用--只是当成简单的表达式语言来使用;也可以在Annotation或XML配置中使用SpEL,这样可以充分利用SpEL简化Spring的Bean配置。
Spring的SpEL
转 spring3.0学习笔记二---SpEL表达式1
相对来讲, java是一门静态语言。而我们今天要讲的是一门动态“语言”---SpEL。
动态语言和静态语言的最显著差别在于,举个例子," 'Hello'.toUperCase()"这只是一个普通的字符串,差别在于能否把它编译和运行起来得到结果。就是说动态语言能把一个字符串解释成程序语句。如果还不是很明白的话没关系,看下面的SpEL例子。(接下去的我就用例子来做介绍了)
public void testSpEL1() {
//ExpressionParser是Spring3里的一个包,用来动态解释一个字符串。
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(" 'Hello,World' ");
System.out.println((String)exp.getValue());
}
这里'Hello,World' 是一个字符串,解释起来还是一个字符串,所以打印结果是:Hello,World
第二个例子:调用方法
public void testSpEL2() {
ExpressionParser parser = new SpelExpressionParser();
Expression exp=parser.parseExpression(" 'Hello'.concat(' World!')"); //这里调用了字符串String的concat方法
//Expression exp=parser.parseExpression("newString('helloworld').toUpperCase()");
Stringmessage=(String)exp.getValue();
}
第三个例子:调用属性
ExpressionParser parser= new SpelExpressionParser();
Expression exp=parser.parseExpression("'HelloWorld'.bytes"); //得到字符串的byte
//Expression exp=parser.parseExpression("'HelloWorld'.bytes.length"); //得到属性的属性
byte [] bytes=(byte[])exp.getValue();
第四个例子:调用类中的属性(下面开始复杂起来了)
@Resource
public User user; //注入之后,user.getName() 为 xiaoling
public void testSpEL() {
//设“值域”,限定在u这个对象里
EvaluationContext context = new StandardEvaluationContext(user);
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("username"); //==user.getUsername()
System.out.println((String)exp.getValue(context)); //结果:xiaoling
}
或者用更简洁的一个方式 :
System.out.println((String)exp.getValue(user));
这样就不用设值域了!呵呵!
第五个例子:给对象中的属性设值
StandardEvaluationContext context = new StandardEvaluationContext(user);
parser.parseExpression("username").setValue(context, "ling");
第六个例子:做判断
Expression exp=parser.parseExpression("name=='xiaoling' ");
boolean result=exp.getValue(context,Boolean.class); //evaluate stotrue
打印出来,结果为true
看到这,可能你还是一头雾水:这算什么新特性啊,哪有什么用处!
用处就在于,SpEL把java变成“动”的了!(纯属我个人观点!!)
接下来,我们把SpEL用到bean.xml中去
先看个例子(例一)
<bean id="numberGuess" class="cn.ling.spel.NumberGuess">
<property name="randomNumber" value="#{T(java.lang.Math).random()*100.0}"/>
</bean>
怎么样,可以在xml文件里面赋值了!呵呵!
value里面都用#{}来赋值。至于T(java.lang.Math),它是指某个类,即Math这个类。
看这个例子(例二):systemProperties
<property name="defaultLocale" value="#{systemProperties['user.region']}"/>
systemProperties是预定义好的,里面有很属性可以用,它就相当于java文件中的System.getProperty("user.region"),它能取出当前计算机所在的国家。
例三:引用xml里面的其它bean
<bean id="numberGuess" class="org.spring.samples.NumberGuess">
<property name="randomNumber" value="#{T(java.lang.Math).random()*100.0}"/>
<!--otherproperties-->
</bean>
<bean id="shapeGuess" class="org.spring.samples.ShapeGuess">
<property name="initialShapeSeed" value="#{numberGuess.randomNumber}"/>
<!--otherproperties-->
</bean>
SpEL还可以用在annotation中:
例一:用在属性上
public static class FieldValueTestBean{
@Value("#{systemProperties['user.region']}")
private String defaultLocale;
//set和get方法
public void setDefaultLocale(StringdefaultLocale) {
this.defaultLocale=defaultLocale;
}
public StringgetDefaultLocale(){
returnthis.defaultLocale;
}
}
例二:用在方法上
public static class PropertyValueTestBean{
private String defaultLocale;
@Value("#{systemProperties['user.region']}")
public void setDefaultLocale(String defaultLocale){
this.defaultLocale=defaultLocale;
}
public String getDefaultLocale(){
return this.defaultLocale;
}
}
}
例三:Autowired和构造器中
public class SimpleMovieLister{
private MovieFinder movieFinder;
private String defaultLocale;
@Autowired
public void configure(MovieFinder movieFinder,
@Value("#{systemProperties['user.region']}"}String defaultLocale){
this.movieFinder=movieFinder;
this.defaultLocale=defaultLocale;
}
//...
}
转 Spring3表达式语言(SpEL)学习笔记
最新地址请访问:http://leeyee.github.io/blog/2011/06/19/spring-expression-language
Spring Excpression Language (SpEL)语言支持在运行时操作和查询对象,其语法类似统一的EL语言,但是SpEL提供了额外的功能。
1、文本表达式
2、布尔类和关系操作
3、正则表达式
4、类表达式
5、访问属性、数组、集合和map
6、方法调用
7、关系操作
8、赋值操作
9、调用构造函数
10、Bean 引用
11、数组构造
12、内联list
13、三元操作
14、变量
15、用户自定义函数
16、集合投影
17、集合选择
18、模板表达式
使用SpEl进行表达式操作,基本操作如下:
第一步,构建解析
[java] view
plain copy
ExpressionParser parser = new SpelExpressionParser();
第二步,使用表达式进行解析
[java] view
plain copy
Expression exp = parser.parseExpression( SpEl);
第三步,获取结果
[java] view
plain copy
exp.getValue()
2.1 文本表达式
文本表达式支持字符表达式、日期、数字(正数、实数及十六进制数)、布尔类型及null.其中字符表达式需要用单引号声明。
对数字支持负数、指数及小数。默认情况下实数使用Double.parseDouble() 进行表达式类型转换
2.2 属性、数组、列表、字典(map)及索引
在表达式中访问类属性时直接使用属性名,属性名首字母大小写均可。
访问数组时可以使用[index]进行元素对象范围。
访问列表时,可直接使用类表的方法,通过点操作符
2.3 内置列表
列表可以直接表示在表达式中使用{}符号表达。{}本身代表一个空的list
2.4 数组构造(spring3.0.3中会抛出异常)
可以通过熟悉的java语法在表达是语言中定义。但目前不支持定义一个初始化的多维数组
2.5 方法
表达式中的方法调用遵循java语法。
2.6 操作符
2.6.1 关系操作符
支持 eq("=="),ne("!="),le("<="),lt("<"),gt(">"),ge(">="),div("/"),mod("%"),not("!"),正则表达式及instanceof操作
2.6.2 逻辑操作符
逻辑操作符支持and,or,not
2.6.3 数学运算操作符
加法运算符可以用于数字,字符串和日期。减法可以用在数字和日期。乘法和除法只能用于对数字。其他受支持的数学运算是模数(%)和指数幂(^)。运行顺序按标准运算符优先级执行
2.7 赋值
通过赋值操作进行属性设置。通常是调用setValue方法,但也可以在调用getValue时设置。
2.8 类型
通过特殊的'T'操作符可以用来指定一个java.lang.Class的实例。在实例话对象的静态方法将会被调用。
2.9 构造器
构造器通过new操作被调用。在new操作时需要指明类的完全类名(包括包路径)
2.10 变量
变量可以通过 #变量名 在表达式中被引用。变量通过StandardEvaluationContext类的setVariable方法进行设置
2.10.1 #this变量
变量 #this 被定义为当前操作对象的引用。
2.11 函数
你可以扩展SpEL通过注册自定义函数。注册后的函数可以在表达式中通过其名称进行调用。函数的注册是通过StandardEvaluationContext类的registerFunction方法进行声明
2.12 三元操作
2.13 Elvis操作
Elvis操作是一个短的三元操作符语法,通常在Groovy语言中使用。
Note: Elvis操作在表达式中可以用来生成默认值,当被访问属性为空时。比如@Value
@Value("#systemPro['mail.port'] ? : 25}") //当mail.port为空时将默认为25
2.14 安全导航操作
该操作是为避免空指针异常。他是来自Groovy语言的。典型的当你有一个指向对象的引用,在你访问其方法或属性时,可能需要验证该对象的方法或属性是否为空,为了避免验证,使用安全导航操作将简单的返回null而不是空指针异常。
2.15 集合选择
选择是一个强大的表达式语言属性,可以使用选择表达式过滤源集合,从而生成一个新的符合选择条件的集合
选择的语法为 ?[selectionExpression] 。他将过滤集合并且返回一个新的集合(原集合的子集)。
选择语句也可用在Map中,过滤keySet及valueSet分别使用key和value关键字
另外:选择语法中,选择符合条件的结果集的第一个元素的语法为 ^[selectionExpression],选择最后一个元素的语法为$[selectionExpression]
2.16 集合投影
语法 ![projectionExpression] 判断集合中每个元素是否符合语法要求
2.17 表达式模板
表达式模板允许混合文字表达式,一个或多个值计算块。每一个值计算块被声明通过可被自定义的前缀和后缀,一般选择使用 #{}作为一个定界符。
------------ 以上就是SpEL的简单介绍。下面直接给出测试用例,这样比较直观,也易于理解。 ------------
pom.xml
[xhtml] view
plain copy
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>study.spring3</groupId>
<artifactId>study-spring3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.5.RELEASE</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.8</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.8</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_3</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
spring-beans.xml
[xhtml] view
plain copy
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 容器注解扫描 -->
<context:component-scan base-package="study.spring.beans" />
<bean id="sputil" name="sputil" class="study.spring.beans.SpElUtil">
<property name="time" value="#{ new java.util.Date()}" />
<property name="name" value="#{'override'}" />
<property name="maps">
<map>
<entry key="1" value="string1" />
<entry key="2" value="string2" />
<entry key="3" value="string3" />
<entry key="4" value="String4" />
</map>
</property>
</bean>
</beans>
ApplicationContextFactory.java
[java] view
plain copy
package study.spring.context.factory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationContextFactory {
private static ApplicationContext ctx;
private ApplicationContextFactory() {
}
public static ApplicationContext createInstance() {
if (ctx == null) {
ctx = new ClassPathXmlApplicationContext(
new String[] { "spring-beans.xml" });
}
return ctx;
}
}
SpElUtil.java
[java] view
plain copy
package study.spring.beans;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class SpElUtil {
private Date time;
private String name;
private SpelTestInnerClass innerClass = new SpelTestInnerClass(
"innerClass", 29);
private List<Integer> numbers;
private Map<Integer, String> maps;
public static Object sayHelloForSpEl(String express) {
ExpressionParser exp = new SpelExpressionParser();
Expression ex = exp.parseExpression(express);
return ex.getValue();
}
/**
* 自定义方法
*
* @param string
* @return
*/
public static int len(String string) {
return string.length();
}
public Map<Integer, String> getMaps() {
return maps;
}
public void setMaps(Map<Integer, String> maps) {
this.maps = maps;
}
public List<Integer> getNumbers() {
return numbers;
}
public void setNumbers(List<Integer> numbers) {
this.numbers = numbers;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SpelTestInnerClass getInnerClass() {
return innerClass;
}
public void setInnerClass(SpelTestInnerClass innerClass) {
this.innerClass = innerClass;
}
}
class SpelTestInnerClass {
private String name;
private int age;
public SpelTestInnerClass(String name, int age) {
this.name = name;
this.age = age;
}
public boolean isGt30ForAge() {
return this.age > 30 ? true : false;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
SpElUtilTest.java
[java] view
plain copy
package study.spring.beans;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import study.spring.context.factory.ApplicationContextFactory;
public class SpElUtilTest {
// spring配置文件上下文
ApplicationContext context = null;
// spring el测试辅助类
SpElUtil spel = null;
// 表达式解析对象
ExpressionParser exp = null;
// 标准赋值上下文
StandardEvaluationContext secontext;
@Before
public void setUp() throws Exception {
context = ApplicationContextFactory.createInstance();
spel = context.getBean(SpElUtil.class);
secontext = new StandardEvaluationContext(spel);
exp = new SpelExpressionParser();
}
@After
public void tearDown() throws Exception {
context = null;
spel = null;
secontext = null;
exp = null;
}
/**
* 文字表达式测试用例
*
* @throws Exception
*/
@Test
public void testSpELLiteralExpression() throws Exception {
// 定义各种文字表达式
String[] lELs = { "'hello SpEL'", "1.028E+7", "0x12EF", "true", "null" };
assertEquals("hello SpEL",
exp.parseExpression(lELs[0]).getValue(String.class));
assertEquals(new Double(10280000), exp.parseExpression(lELs[1])
.getValue(Double.class));
assertEquals(new Integer(4847),
exp.parseExpression(lELs[2]).getValue(Integer.class));
assertTrue(exp.parseExpression(lELs[3]).getValue(Boolean.class));
assertNull(exp.parseExpression(lELs[4]).getValue());
}
/**
* 访问属性、数组、集合和 map 测试
*
* @throws Exception
*/
@Test
public void testSpELProOrArrayOrIndexEtcExpression() throws Exception {
// 属性测试。time为SpElUtil类Date型数据,这里调用Date的属性Year
assertEquals(new Integer(2011), exp.parseExpression("time.Year + 1900")
.getValue(secontext, Integer.class));
// 属性测试。innerClass为SpElUtil类中引入的其他类。
assertEquals(29,
exp.parseExpression("innerClass.age").getValue(secontext));
// 设置SpElUtil类的numbers属性
spel.setNumbers(Arrays.asList(2, 3, 4, 5, 6, 7, 9));
// 访问对象属性数组通过索引
assertEquals(2, exp.parseExpression("numbers[0]").getValue(secontext));
// 访问map
assertEquals("string1",
exp.parseExpression("maps[1]")
.getValue(secontext, String.class));
}
/**
* 内联list测试
*
* @throws Exception
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testSpELInnerListExpression() throws Exception {
// 构造list
List<String> nums = (List<String>) exp.parseExpression(
"{'a','b','c','d'}").getValue();
assertEquals(Arrays.asList("a", "b", "c", "d"), nums);
// 构造List<List<>>
List listOfLists = (List) exp.parseExpression("{{1,2},{3,4}}")
.getValue(secontext);
assertEquals(Arrays.asList(1, 2), listOfLists.get(0));
}
/**
* Array 构造测试
*
* @throws Exception
*/
@Test
public void testSpELArrayConstructionExcpression() throws Exception {
// 创建没有初始值的数组
int[] a = (int[]) exp.parseExpression("new int[4]").getValue();
assertEquals(4, a.length);
// 创建带有初始值的数组
int[] b = (int[]) exp.parseExpression("new int[4]{1,2,3,4}").getValue();
assertEquals(3, b[2]);
// 创建二维数组
int[][] c = (int[][]) exp.parseExpression("new int[4][5]").getValue();
assertEquals(4, c.length);
assertEquals(5, c[0].length);
}
/**
* 方法表达式测试
*
* @throws Exception
*/
@Test
public void testSpELMethodExcpression() throws Exception {
// String.replace方法测试
assertEquals(
"abC2def",
exp.parseExpression("'abcdef'.replace('c','C2')").getValue(
String.class));
// 自定义类方法测试
assertFalse(exp.parseExpression("innerClass.isGt30ForAge()").getValue(
secontext, Boolean.class));
spel.getInnerClass().setAge(34);
assertTrue(exp.parseExpression("innerClass.isGt30ForAge()").getValue(
secontext, Boolean.class));
}
/**
* 操作符、正则表达式测试
*
* @throws Exception
*/
@Test
public void testSpElOperatorAndRegExpression() throws Exception {
// 关系操作
assertTrue(exp.parseExpression("1 == 1").getValue(Boolean.class));
assertTrue(exp.parseExpression("1 eq 1").getValue(Boolean.class));
assertTrue(exp.parseExpression("1 > -1").getValue(Boolean.class));
assertTrue(exp.parseExpression("1 gt -1").getValue(Boolean.class));
assertTrue(exp.parseExpression("'a' < 'b'").getValue(Boolean.class));
assertTrue(exp.parseExpression("'a' lt 'b'").getValue(Boolean.class));
assertTrue(exp.parseExpression(
" new Integer(123) instanceof T(Integer) ").getValue(
Boolean.class));
assertTrue(exp.parseExpression("'5.00' matches '^-?//d+(//.//d{2})?$'")
.getValue(Boolean.class));
// 逻辑操作
assertTrue(exp.parseExpression("true and true").getValue(Boolean.class));
assertTrue(exp.parseExpression("true or false").getValue(Boolean.class));
assertFalse(exp.parseExpression("innerClass.isGt30ForAge() and false ")
.getValue(secontext, Boolean.class));
assertFalse(exp.parseExpression("!innerClass.isGt30ForAge() and true ")
.getValue(secontext, Boolean.class));
assertTrue(exp.parseExpression("!false").getValue(Boolean.class));
// 运算操作
assertEquals(2, exp.parseExpression("1 + 1").getValue());
assertEquals("ABab",
exp.parseExpression("'AB' + 'ab'").getValue(String.class));
assertEquals(25.0,
exp.parseExpression("1 + 2 * 8 div 4 mod 2 + 2 ^ 3 * 3e0")
.getValue());
assertEquals(exp.parseExpression("1 + 2 * 8 / 4 % 2 + 2 ^ 3 ")
.getValue(),
exp.parseExpression("1 + 2 * 8 div 4 mod 2 + 2 ^ 3 ")
.getValue());
}
/**
* 赋值表达式测试
*
* @throws Exception
*/
@SuppressWarnings("deprecation")
@Test
public void testSpelAssignmentExpression() throws Exception {
Date oldDate = spel.getTime();// 获取当前time属性值
exp.parseExpression("time").setValue(secontext, new Date(113, 2, 25)); // 为time属性重新赋值
Date newDate = spel.getTime();// 获取赋值后的time属性值
assertEquals(2013,
exp.parseExpression("time.Year + 1900").getValue(secontext));
assertNotSame(oldDate, newDate);
// 或者使用下属方法赋值
assertEquals("abc",
exp.parseExpression("Name = 'abc'").getValue(secontext));
// 还原time默认,避免后续测试错误
spel.setTime(oldDate);
spel.setName("override");
}
/**
* 类型操作表达式测试
*
* @throws Exception
*/
@SuppressWarnings("rawtypes")
@Test
public void testSpelTypesExpression() throws Exception {
Class dateClass = exp.parseExpression("T(java.util.Date)").getValue(
Class.class);
assertEquals("java.util.Date", dateClass.getName());
assertTrue(exp
.parseExpression(
"T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR")
.getValue(Boolean.class));
}
/**
* 构造函数调用测试
*
* @throws Exception
*/
@Test
public void testSpelConstructorsExpression() throws Exception {
SpelTestInnerClass spt = exp
.parseExpression(
"new study.spring.beans.SpelTestInnerClass('constructTest',23)")
.getValue(SpelTestInnerClass.class);
assertEquals(23, spt.getAge());
assertEquals("constructTest", spt.getName());
}
/**
* 设置变量测试
*
* @throws Exception
*/
@SuppressWarnings("unchecked")
@Test
public void testSpelVariablesExpression() throws Exception {
List<Integer> list = new ArrayList<Integer>();
list.addAll(Arrays.asList(2, 3, 4, 5, 6, 7, 9));
secontext.setVariable("list", list);
List<Integer> vList = (List<Integer>) exp.parseExpression("#list")
.getValue(secontext);
assertEquals(vList, list);
List<Integer> nums = (List<Integer>) exp.parseExpression(
"#list.?[#this >5]").getValue(secontext); // 获取值大于5的元素集合
assertEquals(nums, Arrays.asList(6, 7, 9));
}
/**
* 自定义函数表达式测试
*
* @throws Exception
*/
@Test
public void testSpelFunctionExpression() throws Exception {
StandardEvaluationContext context = new StandardEvaluationContext();
context.registerFunction("len", SpElUtil.class.getDeclaredMethod("len",
new Class[] { String.class }));
assertEquals(3, exp.parseExpression("#len('abc')").getValue(context));
}
@Test
public void testSpelBeanExpression() throws Exception {
}
/**
* 三元操作测试
*
* @throws Exception
*/
@Test
public void testSpelTernaryOperatorExpression() throws Exception {
assertTrue(exp.parseExpression(" true ? true :false").getValue(
Boolean.class));
assertEquals("is true",
exp.parseExpression(" 1 == 1 ? 'is true' :'is false'")
.getValue(String.class));
}
/**
* Elvis 操作测试
*
* @throws Exception
*/
@Test
public void testSpeleElvisOperatorExpression() throws Exception {
Expression ex = exp.parseExpression("name?:'name is null'");
assertEquals("override", ex.getValue(secontext, String.class));
spel.setName(null);
assertEquals("name is null", ex.getValue(secontext, String.class));
spel.setName("override");
}
/**
* 安全导航操作测试
*
* @throws Exception
*/
@Test
public void testSpelSafeNavOperatorExpression() throws Exception {
assertEquals("innerClass", exp.parseExpression("innerClass?.name")
.getValue(secontext, String.class));
spel.setInnerClass(null);
// 使用这种表达式可以避免抛出空指针异常
assertNull(exp.parseExpression("innerClass?.name").getValue(secontext,
String.class));
}
/**
* 集合选择表达式测试
*
* @throws Exception
*/
@SuppressWarnings("unchecked")
@Test
public void testSpelCollectionSelectExpression() throws Exception {
spel.setNumbers(Arrays.asList(2, 3, 4, 5, 6, 7, 9));
List<Integer> nums = (List<Integer>) exp.parseExpression(
"numbers.?[#this >5]").getValue(secontext);
assertEquals(nums, Arrays.asList(6, 7, 9));
// 获取第一个元素
assertEquals(6,
exp.parseExpression("numbers.^[#this > 5]").getValue(secontext));
// 获取最后一个元素
assertEquals(9,
exp.parseExpression("numbers.$[#this > 5]").getValue(secontext));
Map<Integer, String> maps = (Map<Integer, String>) exp.parseExpression(
"maps.?[value == 'string3' ]").getValue(secontext);
Map<Integer, String> tmap = new HashMap<Integer, String>();
tmap.put(3, "string3");
assertEquals(maps, tmap);
Map<Integer, String> mapk = (Map<Integer, String>) exp.parseExpression(
"maps.?[key > 2 and key < 4 ]").getValue(secontext);
assertEquals(mapk, tmap);
}
/**
* 投影表达式测试
*
* @throws Exception
*/
@SuppressWarnings("unchecked")
@Test
public void testSpelProjectionExpression() throws Exception {
spel.setNumbers(Arrays.asList(2, 3, 4, 5, 6));
assertEquals(Arrays.asList(5, 6, 7, 8, 9),
exp.parseExpression("numbers.![#this+3]").getValue(secontext));
List<Integer> keys = (List<Integer>) exp.parseExpression("maps.![key]")
.getValue(secontext);
assertEquals(keys, Arrays.asList(1, 2, 3, 4));
List<String> mapv = (List<String>) exp.parseExpression("maps.![value]")
.getValue(secontext);
assertEquals(mapv,
Arrays.asList("string1", "string2", "string3", "String4"));
List<Boolean> mapK = (List<Boolean>) exp.parseExpression(
"maps.![key > 2 and value !='String4']").getValue(secontext);
assertEquals(mapK, Arrays.asList(false, false, true, false));
}
/**
* 模板语言测试
*
* @throws Exception
*/
@Test
public void testSpelTemplate() throws Exception {
assertEquals(
" this is a test 4",
exp.parseExpression(" this is a test #{ maps.![key].get(3)}",
new TemplateParserContext()).getValue(secontext,
String.class));
}
}
SpEL可以独立于SPring容器使用--只是当成简单的表达式语言来使用;也可以在Annotation或XML配置中使用SpEL,这样可以充分利用SpEL简化Spring的Bean配置。
Spring的SpEL
转 spring3.0学习笔记二---SpEL表达式1
相对来讲, java是一门静态语言。而我们今天要讲的是一门动态“语言”---SpEL。
动态语言和静态语言的最显著差别在于,举个例子," 'Hello'.toUperCase()"这只是一个普通的字符串,差别在于能否把它编译和运行起来得到结果。就是说动态语言能把一个字符串解释成程序语句。如果还不是很明白的话没关系,看下面的SpEL例子。(接下去的我就用例子来做介绍了)
public void testSpEL1() {
//ExpressionParser是Spring3里的一个包,用来动态解释一个字符串。
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(" 'Hello,World' ");
System.out.println((String)exp.getValue());
}
这里'Hello,World' 是一个字符串,解释起来还是一个字符串,所以打印结果是:Hello,World
第二个例子:调用方法
public void testSpEL2() {
ExpressionParser parser = new SpelExpressionParser();
Expression exp=parser.parseExpression(" 'Hello'.concat(' World!')"); //这里调用了字符串String的concat方法
//Expression exp=parser.parseExpression("newString('helloworld').toUpperCase()");
Stringmessage=(String)exp.getValue();
}
第三个例子:调用属性
ExpressionParser parser= new SpelExpressionParser();
Expression exp=parser.parseExpression("'HelloWorld'.bytes"); //得到字符串的byte
//Expression exp=parser.parseExpression("'HelloWorld'.bytes.length"); //得到属性的属性
byte [] bytes=(byte[])exp.getValue();
第四个例子:调用类中的属性(下面开始复杂起来了)
@Resource
public User user; //注入之后,user.getName() 为 xiaoling
public void testSpEL() {
//设“值域”,限定在u这个对象里
EvaluationContext context = new StandardEvaluationContext(user);
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("username"); //==user.getUsername()
System.out.println((String)exp.getValue(context)); //结果:xiaoling
}
或者用更简洁的一个方式 :
System.out.println((String)exp.getValue(user));
这样就不用设值域了!呵呵!
第五个例子:给对象中的属性设值
StandardEvaluationContext context = new StandardEvaluationContext(user);
parser.parseExpression("username").setValue(context, "ling");
第六个例子:做判断
Expression exp=parser.parseExpression("name=='xiaoling' ");
boolean result=exp.getValue(context,Boolean.class); //evaluate stotrue
打印出来,结果为true
看到这,可能你还是一头雾水:这算什么新特性啊,哪有什么用处!
用处就在于,SpEL把java变成“动”的了!(纯属我个人观点!!)
接下来,我们把SpEL用到bean.xml中去
先看个例子(例一)
<bean id="numberGuess" class="cn.ling.spel.NumberGuess">
<property name="randomNumber" value="#{T(java.lang.Math).random()*100.0}"/>
</bean>
怎么样,可以在xml文件里面赋值了!呵呵!
value里面都用#{}来赋值。至于T(java.lang.Math),它是指某个类,即Math这个类。
看这个例子(例二):systemProperties
<property name="defaultLocale" value="#{systemProperties['user.region']}"/>
systemProperties是预定义好的,里面有很属性可以用,它就相当于java文件中的System.getProperty("user.region"),它能取出当前计算机所在的国家。
例三:引用xml里面的其它bean
<bean id="numberGuess" class="org.spring.samples.NumberGuess">
<property name="randomNumber" value="#{T(java.lang.Math).random()*100.0}"/>
<!--otherproperties-->
</bean>
<bean id="shapeGuess" class="org.spring.samples.ShapeGuess">
<property name="initialShapeSeed" value="#{numberGuess.randomNumber}"/>
<!--otherproperties-->
</bean>
SpEL还可以用在annotation中:
例一:用在属性上
public static class FieldValueTestBean{
@Value("#{systemProperties['user.region']}")
private String defaultLocale;
//set和get方法
public void setDefaultLocale(StringdefaultLocale) {
this.defaultLocale=defaultLocale;
}
public StringgetDefaultLocale(){
returnthis.defaultLocale;
}
}
例二:用在方法上
public static class PropertyValueTestBean{
private String defaultLocale;
@Value("#{systemProperties['user.region']}")
public void setDefaultLocale(String defaultLocale){
this.defaultLocale=defaultLocale;
}
public String getDefaultLocale(){
return this.defaultLocale;
}
}
}
例三:Autowired和构造器中
public class SimpleMovieLister{
private MovieFinder movieFinder;
private String defaultLocale;
@Autowired
public void configure(MovieFinder movieFinder,
@Value("#{systemProperties['user.region']}"}String defaultLocale){
this.movieFinder=movieFinder;
this.defaultLocale=defaultLocale;
}
//...
}
转 Spring3表达式语言(SpEL)学习笔记
最新地址请访问:http://leeyee.github.io/blog/2011/06/19/spring-expression-language
Spring Excpression Language (SpEL)语言支持在运行时操作和查询对象,其语法类似统一的EL语言,但是SpEL提供了额外的功能。
1、文本表达式
2、布尔类和关系操作
3、正则表达式
4、类表达式
5、访问属性、数组、集合和map
6、方法调用
7、关系操作
8、赋值操作
9、调用构造函数
10、Bean 引用
11、数组构造
12、内联list
13、三元操作
14、变量
15、用户自定义函数
16、集合投影
17、集合选择
18、模板表达式
使用SpEl进行表达式操作,基本操作如下:
第一步,构建解析
[java] view
plain copy
ExpressionParser parser = new SpelExpressionParser();
第二步,使用表达式进行解析
[java] view
plain copy
Expression exp = parser.parseExpression( SpEl);
第三步,获取结果
[java] view
plain copy
exp.getValue()
2.1 文本表达式
文本表达式支持字符表达式、日期、数字(正数、实数及十六进制数)、布尔类型及null.其中字符表达式需要用单引号声明。
对数字支持负数、指数及小数。默认情况下实数使用Double.parseDouble() 进行表达式类型转换
2.2 属性、数组、列表、字典(map)及索引
在表达式中访问类属性时直接使用属性名,属性名首字母大小写均可。
访问数组时可以使用[index]进行元素对象范围。
访问列表时,可直接使用类表的方法,通过点操作符
2.3 内置列表
列表可以直接表示在表达式中使用{}符号表达。{}本身代表一个空的list
2.4 数组构造(spring3.0.3中会抛出异常)
可以通过熟悉的java语法在表达是语言中定义。但目前不支持定义一个初始化的多维数组
2.5 方法
表达式中的方法调用遵循java语法。
2.6 操作符
2.6.1 关系操作符
支持 eq("=="),ne("!="),le("<="),lt("<"),gt(">"),ge(">="),div("/"),mod("%"),not("!"),正则表达式及instanceof操作
2.6.2 逻辑操作符
逻辑操作符支持and,or,not
2.6.3 数学运算操作符
加法运算符可以用于数字,字符串和日期。减法可以用在数字和日期。乘法和除法只能用于对数字。其他受支持的数学运算是模数(%)和指数幂(^)。运行顺序按标准运算符优先级执行
2.7 赋值
通过赋值操作进行属性设置。通常是调用setValue方法,但也可以在调用getValue时设置。
2.8 类型
通过特殊的'T'操作符可以用来指定一个java.lang.Class的实例。在实例话对象的静态方法将会被调用。
2.9 构造器
构造器通过new操作被调用。在new操作时需要指明类的完全类名(包括包路径)
2.10 变量
变量可以通过 #变量名 在表达式中被引用。变量通过StandardEvaluationContext类的setVariable方法进行设置
2.10.1 #this变量
变量 #this 被定义为当前操作对象的引用。
2.11 函数
你可以扩展SpEL通过注册自定义函数。注册后的函数可以在表达式中通过其名称进行调用。函数的注册是通过StandardEvaluationContext类的registerFunction方法进行声明
2.12 三元操作
2.13 Elvis操作
Elvis操作是一个短的三元操作符语法,通常在Groovy语言中使用。
Note: Elvis操作在表达式中可以用来生成默认值,当被访问属性为空时。比如@Value
@Value("#systemPro['mail.port'] ? : 25}") //当mail.port为空时将默认为25
2.14 安全导航操作
该操作是为避免空指针异常。他是来自Groovy语言的。典型的当你有一个指向对象的引用,在你访问其方法或属性时,可能需要验证该对象的方法或属性是否为空,为了避免验证,使用安全导航操作将简单的返回null而不是空指针异常。
2.15 集合选择
选择是一个强大的表达式语言属性,可以使用选择表达式过滤源集合,从而生成一个新的符合选择条件的集合
选择的语法为 ?[selectionExpression] 。他将过滤集合并且返回一个新的集合(原集合的子集)。
选择语句也可用在Map中,过滤keySet及valueSet分别使用key和value关键字
另外:选择语法中,选择符合条件的结果集的第一个元素的语法为 ^[selectionExpression],选择最后一个元素的语法为$[selectionExpression]
2.16 集合投影
语法 ![projectionExpression] 判断集合中每个元素是否符合语法要求
2.17 表达式模板
表达式模板允许混合文字表达式,一个或多个值计算块。每一个值计算块被声明通过可被自定义的前缀和后缀,一般选择使用 #{}作为一个定界符。
------------ 以上就是SpEL的简单介绍。下面直接给出测试用例,这样比较直观,也易于理解。 ------------
pom.xml
[xhtml] view
plain copy
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>study.spring3</groupId>
<artifactId>study-spring3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.5.RELEASE</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.8</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.8</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_3</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
spring-beans.xml
[xhtml] view
plain copy
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 容器注解扫描 -->
<context:component-scan base-package="study.spring.beans" />
<bean id="sputil" name="sputil" class="study.spring.beans.SpElUtil">
<property name="time" value="#{ new java.util.Date()}" />
<property name="name" value="#{'override'}" />
<property name="maps">
<map>
<entry key="1" value="string1" />
<entry key="2" value="string2" />
<entry key="3" value="string3" />
<entry key="4" value="String4" />
</map>
</property>
</bean>
</beans>
ApplicationContextFactory.java
[java] view
plain copy
package study.spring.context.factory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationContextFactory {
private static ApplicationContext ctx;
private ApplicationContextFactory() {
}
public static ApplicationContext createInstance() {
if (ctx == null) {
ctx = new ClassPathXmlApplicationContext(
new String[] { "spring-beans.xml" });
}
return ctx;
}
}
SpElUtil.java
[java] view
plain copy
package study.spring.beans;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class SpElUtil {
private Date time;
private String name;
private SpelTestInnerClass innerClass = new SpelTestInnerClass(
"innerClass", 29);
private List<Integer> numbers;
private Map<Integer, String> maps;
public static Object sayHelloForSpEl(String express) {
ExpressionParser exp = new SpelExpressionParser();
Expression ex = exp.parseExpression(express);
return ex.getValue();
}
/**
* 自定义方法
*
* @param string
* @return
*/
public static int len(String string) {
return string.length();
}
public Map<Integer, String> getMaps() {
return maps;
}
public void setMaps(Map<Integer, String> maps) {
this.maps = maps;
}
public List<Integer> getNumbers() {
return numbers;
}
public void setNumbers(List<Integer> numbers) {
this.numbers = numbers;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SpelTestInnerClass getInnerClass() {
return innerClass;
}
public void setInnerClass(SpelTestInnerClass innerClass) {
this.innerClass = innerClass;
}
}
class SpelTestInnerClass {
private String name;
private int age;
public SpelTestInnerClass(String name, int age) {
this.name = name;
this.age = age;
}
public boolean isGt30ForAge() {
return this.age > 30 ? true : false;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
SpElUtilTest.java
[java] view
plain copy
package study.spring.beans;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import study.spring.context.factory.ApplicationContextFactory;
public class SpElUtilTest {
// spring配置文件上下文
ApplicationContext context = null;
// spring el测试辅助类
SpElUtil spel = null;
// 表达式解析对象
ExpressionParser exp = null;
// 标准赋值上下文
StandardEvaluationContext secontext;
@Before
public void setUp() throws Exception {
context = ApplicationContextFactory.createInstance();
spel = context.getBean(SpElUtil.class);
secontext = new StandardEvaluationContext(spel);
exp = new SpelExpressionParser();
}
@After
public void tearDown() throws Exception {
context = null;
spel = null;
secontext = null;
exp = null;
}
/**
* 文字表达式测试用例
*
* @throws Exception
*/
@Test
public void testSpELLiteralExpression() throws Exception {
// 定义各种文字表达式
String[] lELs = { "'hello SpEL'", "1.028E+7", "0x12EF", "true", "null" };
assertEquals("hello SpEL",
exp.parseExpression(lELs[0]).getValue(String.class));
assertEquals(new Double(10280000), exp.parseExpression(lELs[1])
.getValue(Double.class));
assertEquals(new Integer(4847),
exp.parseExpression(lELs[2]).getValue(Integer.class));
assertTrue(exp.parseExpression(lELs[3]).getValue(Boolean.class));
assertNull(exp.parseExpression(lELs[4]).getValue());
}
/**
* 访问属性、数组、集合和 map 测试
*
* @throws Exception
*/
@Test
public void testSpELProOrArrayOrIndexEtcExpression() throws Exception {
// 属性测试。time为SpElUtil类Date型数据,这里调用Date的属性Year
assertEquals(new Integer(2011), exp.parseExpression("time.Year + 1900")
.getValue(secontext, Integer.class));
// 属性测试。innerClass为SpElUtil类中引入的其他类。
assertEquals(29,
exp.parseExpression("innerClass.age").getValue(secontext));
// 设置SpElUtil类的numbers属性
spel.setNumbers(Arrays.asList(2, 3, 4, 5, 6, 7, 9));
// 访问对象属性数组通过索引
assertEquals(2, exp.parseExpression("numbers[0]").getValue(secontext));
// 访问map
assertEquals("string1",
exp.parseExpression("maps[1]")
.getValue(secontext, String.class));
}
/**
* 内联list测试
*
* @throws Exception
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testSpELInnerListExpression() throws Exception {
// 构造list
List<String> nums = (List<String>) exp.parseExpression(
"{'a','b','c','d'}").getValue();
assertEquals(Arrays.asList("a", "b", "c", "d"), nums);
// 构造List<List<>>
List listOfLists = (List) exp.parseExpression("{{1,2},{3,4}}")
.getValue(secontext);
assertEquals(Arrays.asList(1, 2), listOfLists.get(0));
}
/**
* Array 构造测试
*
* @throws Exception
*/
@Test
public void testSpELArrayConstructionExcpression() throws Exception {
// 创建没有初始值的数组
int[] a = (int[]) exp.parseExpression("new int[4]").getValue();
assertEquals(4, a.length);
// 创建带有初始值的数组
int[] b = (int[]) exp.parseExpression("new int[4]{1,2,3,4}").getValue();
assertEquals(3, b[2]);
// 创建二维数组
int[][] c = (int[][]) exp.parseExpression("new int[4][5]").getValue();
assertEquals(4, c.length);
assertEquals(5, c[0].length);
}
/**
* 方法表达式测试
*
* @throws Exception
*/
@Test
public void testSpELMethodExcpression() throws Exception {
// String.replace方法测试
assertEquals(
"abC2def",
exp.parseExpression("'abcdef'.replace('c','C2')").getValue(
String.class));
// 自定义类方法测试
assertFalse(exp.parseExpression("innerClass.isGt30ForAge()").getValue(
secontext, Boolean.class));
spel.getInnerClass().setAge(34);
assertTrue(exp.parseExpression("innerClass.isGt30ForAge()").getValue(
secontext, Boolean.class));
}
/**
* 操作符、正则表达式测试
*
* @throws Exception
*/
@Test
public void testSpElOperatorAndRegExpression() throws Exception {
// 关系操作
assertTrue(exp.parseExpression("1 == 1").getValue(Boolean.class));
assertTrue(exp.parseExpression("1 eq 1").getValue(Boolean.class));
assertTrue(exp.parseExpression("1 > -1").getValue(Boolean.class));
assertTrue(exp.parseExpression("1 gt -1").getValue(Boolean.class));
assertTrue(exp.parseExpression("'a' < 'b'").getValue(Boolean.class));
assertTrue(exp.parseExpression("'a' lt 'b'").getValue(Boolean.class));
assertTrue(exp.parseExpression(
" new Integer(123) instanceof T(Integer) ").getValue(
Boolean.class));
assertTrue(exp.parseExpression("'5.00' matches '^-?//d+(//.//d{2})?$'")
.getValue(Boolean.class));
// 逻辑操作
assertTrue(exp.parseExpression("true and true").getValue(Boolean.class));
assertTrue(exp.parseExpression("true or false").getValue(Boolean.class));
assertFalse(exp.parseExpression("innerClass.isGt30ForAge() and false ")
.getValue(secontext, Boolean.class));
assertFalse(exp.parseExpression("!innerClass.isGt30ForAge() and true ")
.getValue(secontext, Boolean.class));
assertTrue(exp.parseExpression("!false").getValue(Boolean.class));
// 运算操作
assertEquals(2, exp.parseExpression("1 + 1").getValue());
assertEquals("ABab",
exp.parseExpression("'AB' + 'ab'").getValue(String.class));
assertEquals(25.0,
exp.parseExpression("1 + 2 * 8 div 4 mod 2 + 2 ^ 3 * 3e0")
.getValue());
assertEquals(exp.parseExpression("1 + 2 * 8 / 4 % 2 + 2 ^ 3 ")
.getValue(),
exp.parseExpression("1 + 2 * 8 div 4 mod 2 + 2 ^ 3 ")
.getValue());
}
/**
* 赋值表达式测试
*
* @throws Exception
*/
@SuppressWarnings("deprecation")
@Test
public void testSpelAssignmentExpression() throws Exception {
Date oldDate = spel.getTime();// 获取当前time属性值
exp.parseExpression("time").setValue(secontext, new Date(113, 2, 25)); // 为time属性重新赋值
Date newDate = spel.getTime();// 获取赋值后的time属性值
assertEquals(2013,
exp.parseExpression("time.Year + 1900").getValue(secontext));
assertNotSame(oldDate, newDate);
// 或者使用下属方法赋值
assertEquals("abc",
exp.parseExpression("Name = 'abc'").getValue(secontext));
// 还原time默认,避免后续测试错误
spel.setTime(oldDate);
spel.setName("override");
}
/**
* 类型操作表达式测试
*
* @throws Exception
*/
@SuppressWarnings("rawtypes")
@Test
public void testSpelTypesExpression() throws Exception {
Class dateClass = exp.parseExpression("T(java.util.Date)").getValue(
Class.class);
assertEquals("java.util.Date", dateClass.getName());
assertTrue(exp
.parseExpression(
"T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR")
.getValue(Boolean.class));
}
/**
* 构造函数调用测试
*
* @throws Exception
*/
@Test
public void testSpelConstructorsExpression() throws Exception {
SpelTestInnerClass spt = exp
.parseExpression(
"new study.spring.beans.SpelTestInnerClass('constructTest',23)")
.getValue(SpelTestInnerClass.class);
assertEquals(23, spt.getAge());
assertEquals("constructTest", spt.getName());
}
/**
* 设置变量测试
*
* @throws Exception
*/
@SuppressWarnings("unchecked")
@Test
public void testSpelVariablesExpression() throws Exception {
List<Integer> list = new ArrayList<Integer>();
list.addAll(Arrays.asList(2, 3, 4, 5, 6, 7, 9));
secontext.setVariable("list", list);
List<Integer> vList = (List<Integer>) exp.parseExpression("#list")
.getValue(secontext);
assertEquals(vList, list);
List<Integer> nums = (List<Integer>) exp.parseExpression(
"#list.?[#this >5]").getValue(secontext); // 获取值大于5的元素集合
assertEquals(nums, Arrays.asList(6, 7, 9));
}
/**
* 自定义函数表达式测试
*
* @throws Exception
*/
@Test
public void testSpelFunctionExpression() throws Exception {
StandardEvaluationContext context = new StandardEvaluationContext();
context.registerFunction("len", SpElUtil.class.getDeclaredMethod("len",
new Class[] { String.class }));
assertEquals(3, exp.parseExpression("#len('abc')").getValue(context));
}
@Test
public void testSpelBeanExpression() throws Exception {
}
/**
* 三元操作测试
*
* @throws Exception
*/
@Test
public void testSpelTernaryOperatorExpression() throws Exception {
assertTrue(exp.parseExpression(" true ? true :false").getValue(
Boolean.class));
assertEquals("is true",
exp.parseExpression(" 1 == 1 ? 'is true' :'is false'")
.getValue(String.class));
}
/**
* Elvis 操作测试
*
* @throws Exception
*/
@Test
public void testSpeleElvisOperatorExpression() throws Exception {
Expression ex = exp.parseExpression("name?:'name is null'");
assertEquals("override", ex.getValue(secontext, String.class));
spel.setName(null);
assertEquals("name is null", ex.getValue(secontext, String.class));
spel.setName("override");
}
/**
* 安全导航操作测试
*
* @throws Exception
*/
@Test
public void testSpelSafeNavOperatorExpression() throws Exception {
assertEquals("innerClass", exp.parseExpression("innerClass?.name")
.getValue(secontext, String.class));
spel.setInnerClass(null);
// 使用这种表达式可以避免抛出空指针异常
assertNull(exp.parseExpression("innerClass?.name").getValue(secontext,
String.class));
}
/**
* 集合选择表达式测试
*
* @throws Exception
*/
@SuppressWarnings("unchecked")
@Test
public void testSpelCollectionSelectExpression() throws Exception {
spel.setNumbers(Arrays.asList(2, 3, 4, 5, 6, 7, 9));
List<Integer> nums = (List<Integer>) exp.parseExpression(
"numbers.?[#this >5]").getValue(secontext);
assertEquals(nums, Arrays.asList(6, 7, 9));
// 获取第一个元素
assertEquals(6,
exp.parseExpression("numbers.^[#this > 5]").getValue(secontext));
// 获取最后一个元素
assertEquals(9,
exp.parseExpression("numbers.$[#this > 5]").getValue(secontext));
Map<Integer, String> maps = (Map<Integer, String>) exp.parseExpression(
"maps.?[value == 'string3' ]").getValue(secontext);
Map<Integer, String> tmap = new HashMap<Integer, String>();
tmap.put(3, "string3");
assertEquals(maps, tmap);
Map<Integer, String> mapk = (Map<Integer, String>) exp.parseExpression(
"maps.?[key > 2 and key < 4 ]").getValue(secontext);
assertEquals(mapk, tmap);
}
/**
* 投影表达式测试
*
* @throws Exception
*/
@SuppressWarnings("unchecked")
@Test
public void testSpelProjectionExpression() throws Exception {
spel.setNumbers(Arrays.asList(2, 3, 4, 5, 6));
assertEquals(Arrays.asList(5, 6, 7, 8, 9),
exp.parseExpression("numbers.![#this+3]").getValue(secontext));
List<Integer> keys = (List<Integer>) exp.parseExpression("maps.![key]")
.getValue(secontext);
assertEquals(keys, Arrays.asList(1, 2, 3, 4));
List<String> mapv = (List<String>) exp.parseExpression("maps.![value]")
.getValue(secontext);
assertEquals(mapv,
Arrays.asList("string1", "string2", "string3", "String4"));
List<Boolean> mapK = (List<Boolean>) exp.parseExpression(
"maps.![key > 2 and value !='String4']").getValue(secontext);
assertEquals(mapK, Arrays.asList(false, false, true, false));
}
/**
* 模板语言测试
*
* @throws Exception
*/
@Test
public void testSpelTemplate() throws Exception {
assertEquals(
" this is a test 4",
exp.parseExpression(" this is a test #{ maps.![key].get(3)}",
new TemplateParserContext()).getValue(secontext,
String.class));
}
}
相关文章推荐
- Java学习
- Java泛型通配符super使用Demo
- Java虚拟机内存模型
- java反射
- spring+shiro+cas的整合问题之循环重定向
- Java System.getProperty()方法获取系统信息
- Java之泛型练习
- Java基础复习系列三
- 20145232 韩文浩 《Java程序设计》第2周学习总结
- 了解HashMap的get和put内部的工作原理,需要理解透Java HashMap的原理
- Java中的除
- Java eclipse下 Ant build.xml实例详解 附完整项目源码
- java继承
- 简单探讨java中String类的hashCode()
- Java配置环境变量
- Java Thread Join Example with Explanation
- 区间求交集算法
- java web开发_购物车功能实现
- java中子类能不能继承父类的私有成员
- spring集成httpclient配置