Spring(23)——SPEL表达式(一)

简介: 23 SpEl 23.1 简介 Spring也有自己的EL,叫Spring Expression Language,简称SpEl。其可以在程序中单独使用,也可以在Spring应用中进行bean定义时使用。

23 SpEl

23.1 简介

Spring也有自己的EL,叫Spring Expression Language,简称SpEl。其可以在程序中单独使用,也可以在Spring应用中进行bean定义时使用。其核心是org.springframework.expression.Expression接口,Spring使用该接口来表示EL中的表达式。通过Expression接口的系列getValue()方法我们可以获取对应Expression在特定EvaluationContext下的值,也可以通过其系列setValue()方法来设值。对应的Expression通常不是由我们直接来new对应实现类的实例,而是通过Spring提供的org.springframework.expression.ExpressionParser接口的系列parseExpression()方法来将一个字符串类型的表达式解析为一个Expression。以下是一个简单的示例,在该示例中我们将字符串表达式“1+2”解析为一个Expression,然后进行计算得出其值为3。

@Test
public void test() {
	String expressionStr = "1+2";
	ExpressionParser parser = new SpelExpressionParser();
	Expression expression = parser.parseExpression(expressionStr);
	Integer val = expression.getValue(Integer.class);
	System.out.println(expressionStr + "的结果是:" + val);
}

Expression接口有一系列的getValue()方法,当其不接收任何参数时表示将会把Expression的计算结果当做一个Object进行返回,如果我们希望返回的是特定的类型,则可以传递对应的类型作为getValue()方法的参数,如上述示例中传递的Interger.class。我们也可以通过给Expression的getValue()方法传递EvaluationContext用以获取在特定环境下的计算结果,也可以传递一个Object作为Expression计算的rootObject。关于Expression接口的更多介绍请参考Spring的API文档。

23.2 示例

SpEl可以支持一般的算术运算,也可以支持逻辑运算,还可以支持对象的方法调用等。下面我们来看一些对应用法的示例。

23.2.1 算术运算

SpEl支持的算术运算可以是加、减、乘、除、求余、指数等。下面是一个对应的示例。

@Test
public void test01() {
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("(1+2)*5 + 8-6/2").getValue().equals(20));//加减乘除
	Assert.assertTrue(parser.parseExpression("8%3").getValue().equals(2));//求余
	Assert.assertTrue(parser.parseExpression("2.0e3").getValue().equals(2000.0));//指数
	Assert.assertTrue(parser.parseExpression("2^3").getValue().equals(8));//指数
}

23.2.2 逻辑运算

逻辑运算就是我们熟悉的与、或、非,在SpEl中就对应“and”、“or”和“!”。

@Test
public void test02() {
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("true and true").getValue(Boolean.class));//
	Assert.assertTrue(parser.parseExpression("true or false").getValue(Boolean.class));//
	Assert.assertTrue(parser.parseExpression("!false").getValue(Boolean.class));//
}

23.2.3 比较运算

比较运算就是我们熟悉的大于(>)、大于等于(>=)、小于(<)、小于等于(<=)、等于(==)和不等于(!=)。

@Test
public void test03() {
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("5>3").getValue(Boolean.class));
	Assert.assertTrue(parser.parseExpression("5<=8").getValue(Boolean.class));
	Assert.assertTrue(parser.parseExpression("5==5").getValue(Boolean.class));
	Assert.assertTrue(parser.parseExpression("5!=6").getValue(Boolean.class));
}

23.2.4 字符串

SpEl允许我们在表达式中直接使用int、double、String等。我们的Expression可以通过对应的字符串进行解析,那么当我们的表达式就是需要表示一个字符串时应该如何表示呢?这个时候需要通过单引号“’”来进行包裹。而当我们的字符串中包含单引号时,那么对应的单引号需要使用一个单引号进行转义,即连续两个单引号。

@Test
public void test04() {
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("'abc'").getValue().equals("abc"));
	Assert.assertTrue(parser.parseExpression("'''abc'").getValue().equals("'abc"));
}

23.2.5 访问方法

在SpEl表达式中我们也可以直接访问对象的方法。在下述示例中我们就直接在SpEl中访问了字符串的length()方法。

@Test
public void test05() {
	ExpressionParser parser = new SpelExpressionParser();
	//直接访问String的length()方法。
	Assert.assertTrue(parser.parseExpression("'abc'.length()").getValue().equals(3));
}

23.2.6 使用EvaluationContext

我们先来看一个例子,在下列示例中我们在表达式中直接写name和getName(),这个时候Expression是无法解析的,因为其不知道name和getName()对应什么意思。

@Test
public void test06() {
	ExpressionParser parser = new SpelExpressionParser();
	parser.parseExpression("name").getValue();
	parser.parseExpression("getName()").getValue();
}

通过指定EvaluationContext我们就可以让name和getName()变得有意义。指定了EvaluationContext之后,Expression将根据对应的EvaluationContext来进行解析。如下示例中我们构建了一个基于user对象的EvaluationContext,user对象将作为StandardEvaluationContext的rootObject,那么对应的Expression就将根据该rootObject对象来获取对应表达式的值。我们可以看到user对象定义了一个getName()方法,在解析name和getName()表达式时都将访问user对象的getName()方法,即它们的返回结果都为字符串“abc”。

@Test
public void test06() {
	Object user = new Object() {
		public String getName() {
			return "abc";
		}
	};
	EvaluationContext context = new StandardEvaluationContext(user);
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("name").getValue(context, String.class).equals("abc"));
	Assert.assertTrue(parser.parseExpression("getName()").getValue(context, String.class).equals("abc"));
}

上述示例中的表达式name表示对应EvaluationContext的rootObject的一个属性,在进行解析时,如果对应的get方法存在,则将直接访问对应的get方法,如上述示例中的getName(),否则将直接对其进行访问,这个时候就需要我们的属性是公有的,以便外部类可以访问。
对于对象而言,我们可以访问其属性的属性或方法,中间以点进行连接。

23.2.7 使用rootObject

当我们的表达式是基于某一个对象的时,我们也可以把对应的对象作为一个rootObject传递给对应的Expression以进行取值。如上述示例我们也可以直接将user对象作为rootObject传递给对应的Expression以获取对应的值。

@Test
public void test07() {
	Object user = new Object() {
		public String getName() {
			return "abc";
		}
	};
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("name").getValue(user, String.class).equals("abc"));
	Assert.assertTrue(parser.parseExpression("getName()").getValue(user, String.class).equals("abc"));
}

23.2.8 List、Array、Map等元素的访问

在SpEl中我们可以通过索引的形式访问List或Array的某一个元素,对应的索引是从0开始的,以“list[index]”的形式出现。如下述示例中的test08_1和test08_2。

@Test
public void test08_1() {
	Object user = new Object() {
		public List<String> getInterests() {
			List<String> interests = Arrays.asList(new String[] {"BasketBall", "FootBall"});
			return interests;
		}
	};
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("interests[0]").getValue(user, String.class).equals("BasketBall"));
	Assert.assertTrue(parser.parseExpression("interests[1]").getValue(user, String.class).equals("FootBall"));
}
	
@Test
public void test08_2() {
	Object user = new Object() {
		public String[] getInterests() {
			return new String[] {"BasketBall", "FootBall"};
		}
	};
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("interests[0]").getValue(user, String.class).equals("BasketBall"));
	Assert.assertTrue(parser.parseExpression("interests[1]").getValue(user, String.class).equals("FootBall"));
}

而对于Map而言,则是通过类似于“map[key]”的形式访问对应的元素的。示例如下。

@Test
public void test08_3() {
	Object user = new Object() {
		public Map<String, String> getInterests() {
			Map<String, String> interests = new HashMap<String, String>();
			interests.put("key1", "BasketBall");
			interests.put("key2", "FootBall");
			return interests;
		}
	};
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("interests['key1']").getValue(user, String.class).equals("BasketBall"));
	Assert.assertTrue(parser.parseExpression("interests['key2']").getValue(user, String.class).equals("FootBall"));
}

 

 

目录
相关文章
|
4月前
|
Java Maven Spring
【Spring】EL表达式失效的问题(添加 isELIgnored)
【Spring】EL表达式失效的问题(添加 isELIgnored)
|
18天前
|
安全 Java 数据安全/隐私保护
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
40 1
|
2月前
|
XML 前端开发 Java
深入理解Spring EL表达式的高级功能
深入理解Spring EL表达式的高级功能
65 1
|
2月前
|
XML 前端开发 Java
掌握Spring EL表达式的基础知识
掌握Spring EL表达式的基础知识
38 1
|
3月前
|
XML Java 数据格式
spring AOP切入点execution表达式
spring AOP切入点execution表达式
|
4月前
|
XML Java 数据格式
演示spring AOP的切入表达式重用和优先级问题以及怎么实现基于xml的AOP
演示spring AOP的切入表达式重用和优先级问题以及怎么实现基于xml的AOP
35 0
|
4月前
|
XML Java 数据格式
spring通过文件属性注入bean和基于xml的bean的自动装配以及spring-eel表达式的使用加代码合集
spring通过文件属性注入bean和基于xml的bean的自动装配以及spring-eel表达式的使用加代码合集
48 0
|
4月前
|
Java Spring
spel获取spring bean
spel获取spring bean
36 0
|
5月前
|
Java Spring
Spring中的表达式语言SpEL详解
Spring中的表达式语言SpEL详解
56 0
|
6月前
|
Java API Spring
Spring判断方法名是符合给定的SPEL+表达式的+API
Spring判断方法名是符合给定的SPEL+表达式的+API
53 0