4. Spring Expression Language (SpEL)
4.1. Introduction
The Spring Expression Language (SpEL for short) is a powerful expression language that supports querying and manipulating an object graph at runtime. The language syntax is similar to Unified EL but offers additional features, most notably method invocation and basic string templating functionality.
While there are several other Java expression languages available, OGNL, MVEL, and JBoss EL, to name a few, the Spring Expression Language was created to provide the Spring community with a single well supported expression language that can be used across all the products in the Spring portfolio. Its language features are driven by the requirements of the projects in the Spring portfolio, including tooling requirements for code completion support within the eclipse based Spring Tool Suite. That said, SpEL is based on a technology agnostic API allowing other expression language implementations to be integrated should the need arise.
While SpEL serves as the foundation for expression evaluation within the Spring portfolio, it is not directly tied to Spring and can be used independently. In order to be self contained, many of the examples in this chapter use SpEL as if it were an independent expression language. This requires creating a few bootstrapping infrastructure classes such as the parser. Most Spring users will not need to deal with this infrastructure and will instead only author expression strings for evaluation. An example of this typical use is the integration of SpEL into creating XML or annotated based bean definitions as shown in the section Expression support for defining bean definitions.
This chapter covers the features of the expression language, its API, and its language syntax. In several places an Inventor and Inventorrsquo;s Society class are used as the target objects for expression evaluation. These class declarations and the data used to populate them are listed at the end of the chapter.
4.2. Feature overview
The expression language supports the following functionality
bull; Literal expressions
bull; Boolean and relational operators
bull; Regular expressions
bull; Class expressions
bull; Accessing properties, arrays, lists, maps
bull; Method invocation
bull; Relational operators
bull; Assignment
bull; Calling constructors
bull; Bean references
bull; Array construction
bull; Inline lists
bull; Inline maps
bull; Ternary operator
bull; Variables
bull; User defined functions
bull; Collection projection
bull; Collection selection
bull; Templated expressions
4.3. Expression evaluation using Springrsquo;s Expression interface
This section introduces the simple use of SpEL interfaces and its expression language. The complete language reference can be found in the sectionLanguage Reference.
The following code introduces the SpEL API to evaluate the literal string expression #39;Hello World#39;.
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression('#39;Hello World#39;');
String message = (String) exp.getValue();
The value of the message variable is simply #39;Hello World#39;.
The SpEL classes and interfaces you are most likely to use are located in the packages org.springframework.expression and its sub packages and spel.support.
The interface ExpressionParser is responsible for parsing an expression string. In this example the expression string is a string literal denoted by the surrounding single quotes. The interface Expression is responsible for evaluating the previously defined expression string. There are two exceptions that can be thrown, ParseException and EvaluationException when calling parser.parseExpression and exp.getValue respectively.
SpEL supports a wide range of features, such as calling methods, accessing properties, and calling constructors.
As an example of method invocation, we call the concat method on the string literal.
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression('#39;Hello World#39;.concat(#39;!#39;)');
String message = (String) exp.getValue();
The value of message is now #39;Hello World!#39;.
As an example of calling a JavaBean property, the String property Bytes can be called as shown below.
ExpressionParser parser = new SpelExpressionParser();
// invokes #39;getBytes()#39;
Expression exp = parser.parseExpression('#39;Hello World#39;.bytes');
byte[] bytes = (byte[]) exp.getValue();
SpEL also supports nested properties using standard dot notation, i.e. prop1.prop2.prop3 and the setting of property values
Public fields may also be accessed.
ExpressionParser parser = new SpelExpressionParser();
// invokes #39;getBytes().length#39;
Expression exp = parser.parseExpression('#39;Hello World#39;.bytes.length');
int length = (Integer) exp.getValue();
The Stringrsquo;s constructor can be called instead of using a string literal.
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression('new String(#39;hello world#39;).toUpperCase()');
String message = exp.getValue(String.class);
Note the use of the generic method public lt;Tgt; T getValue(Classlt;Tgt; desiredResultType). Using this method removes the need to cast the value of the expression to the desired result type. An EvaluationException will be thrown if the value cannot be cast to the type T or converted using the registered type converter.
The more common usage of SpEL is to provide an expression string that is evaluated against a specific object instance (called the root object). There are two options here and which to choose depends on whether the object against which the expression is being evaluated will be changing with each call to evaluate the expression. In the following example we retrieve the name property from an i
全文共34946字,剩余内容已隐藏,支付完成后下载完整资料
4 Spring表达式语言(SpEL)
4.1 引言
Spring表达式语言(简称SpEL)是一门强大的表达式语言,支持在运行时查询和操作对象图。其语言语法类似于统一EL,但是它提供了额外特性,特别是方法调用和基本字符串模板功能。
可供使用的Java表达式语言还有几种,比如OGNL,MVEL,和JBoss EL。Spring表达式语言的创建旨在向Spring社区提供一种单一的支持良好的表达式语言,这种语言可以用于Spring portfolio的所有产品中。它的语言特性受Spring portfolio项目需求的影响,包括Eclipse中基于Spring Tool Suite的代码实现支持的工具需求。也就是说,SpEL是基于技术不可知的API,它在必要时允许集成其它表达式语言进行实现。
尽管在Spring portfolio中SpEL是表达式求值的基础,但它与Spring没有直接的关系,可以单独地使用。为了便于读者阅读和理解,本章的许多示例都将SpEL作为一种独立的表达式语言来使用。这需要创建一些基础类,如解析器。而大多数Spring用户无需在意这些基础类,只须创建表达式字符串用于求值。关于这一用法的典型例子是将SpEL集成到创建XML或基于注释的bean定义中,如4.4部分所示。
本章主要介绍该表达式语言的特点,其API以及语法。在一些地方,Inventor和Inventor的Society类被用作表达式求值的目标对象。这些类的声明和其数据会在本章最后列出。
4.2 功能概述
该表达式语言支持下述功能:
- 文字表达
- 布尔和关系运算符
- 常用表达
- 类表达式
- 访问属性,数组,列表,映射
- 方法调用
- 关系运算符
- 赋值
- 调用构造函数
- Bean引用
- 阵列构建
- 内联列表
- 内联映射
- 三元表达式
- 变量
- 用户定义的功能
- 集合投影
- 集合选择
- 模板表达式
4.3 使用Spring的Expression接口进行表达式求值
本节简单介绍了SpEL接口的用法及其表达式语言。在语言参考一节中可以找到完整的语言参考。
以下代码引入了SpEL API来对字符串表达式“Hello World”进行求值。
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression('#39;Hello World#39;');
String message = (String) exp.getValue();
变量message的值就是#39;Hello World#39;。
你最可能使用到的SpEL类和接口位于程序包 org.springframework.expression及其子程序包spel.support中。
接口ExpressionParser负责解析表达式字符串。在这个例子中,表达式字符串是由单引号括起来的字符串文字。接口Expression对已定义的表达式字符串进行求值。调用时可以抛出两个异常:调用parser.parseExpression时抛出ParseException,调用exp.getValue时抛出EvaluationException。
SpEL支持广泛的功能,例如调用方法,访问属性和调用构造函数。
以下是方法调用的例子,在这个字符串中我们调用了concat方法。
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression('#39;Hello World#39;.concat(#39;!#39;)');
String message = (String) exp.getValue();
Message现在的值是#39;Hello World!#39;。
以下是调用JavaBean属性的示例,它调用了String的属性Bytes。
ExpressionParser parser = new SpelExpressionParser();
// invokes #39;getBytes()#39;
Expression exp = parser.parseExpression('#39;Hello World#39;.bytes');
byte[] bytes = (byte[]) exp.getValue();
SpEL还支持嵌套使用标准点符号的属性,即prop1.prop2.prop3,和属性值的设置。
公共字段也可以被访问。
ExpressionParser parser = new SpelExpressionParser();
// invokes #39;getBytes().length#39;
Expression exp = parser.parseExpression('#39;Hello World#39;.bytes.length');
int length = (Integer) exp.getValue();
可以调用String的构造函数,但不能直接使用字符串。
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression('new String(#39;hello world#39;).toUpperCase()');
String message = exp.getValue(String.class);
请注意通用方法public lt;Tgt; T getValue(Classlt;Tgt; desiredResultType)的使用。使用此方法不需要将表达式的值转换为所需的结果类型。如果该值无法转换为T类型或无法使用注册类型转换器进行转换,则将抛出EvaluationException。
SpEL更常见的用法是提供一个针对特定对象实例(称为根对象)进行求值的表达式字符串。通常有两种选择,哪种选择取决于表达式求值的对象是否随每次调用而改变以求值。在以下示例中,我们从Inventor类的实例中检索name属性。
// Create and set a calendar
GregorianCalendar c = new GregorianCalendar();
c.set(1856, 7, 9);
// The constructor arguments are name, birthday, and nationality.
Inventor tesla = new Inventor('Nikola Tesla', c.getTime(), 'Serbian');
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression('name');
EvaluationContext context = new StandardEvaluationContext(tesla);
String name = (String) exp.getValue(context);
在最后一行中,字符串变量name的值被设为“Nikola Tesla”。您可以通过类StandardEvaluationContext是来指定针对哪个对象的name属性进行求值。如果根对象不太可能改变,这是一种可供使用的机制,它可以简单地在求值语境中设置。如果根对象可能会重复更改,则可以在每次调用时调用getValue方法,如下所示:
// Create and set a calendar
GregorianCalendar c = new GregorianCalendar();
c.set(1856, 7, 9);
// The constructor arguments are name, birthday, and nationality.
Inventor tesla = new Inventor('Nikola Tesla', c.getTime(), 'Serbian');
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression('name');
String name = (String) exp.getValue(tesla);
在此例中,getValue方法直接使用tesla,表达式求值环境在内部创建了默认的求值语境—— 它不需要外部提供。
StandardEvaluationContext构建起来代价较大,在重复使用期间,它建立起缓存状态,使得表达式求值得到更快的处理。因此,应尽可能地使用缓存和复用,而不要为每一次表达式求值重新构建。
在某些情况下,可能需要使用现成的求值语境,但在每次调用时须提供不同的根对象给getValue方法。getValue方法允许在同一次调用中指定两者。在这些情况下,传递给调用的根对象将被重载求值语境中指定的对象(可能为null)。
在独立使用SpEL时,需要创建解析器、解析表达式,并可能需要提供求值语境和根语境对象。然而,更常见的用法是只提供SpEL表达式字符串,将其作为配置文件的一部分,例如Spring bean或Spring Web Flow定义。在这种情况下,解析器,求值语境,根对象和任何预定义的变量都是隐式设置的,这要求用户除了表达式以外什么也不能指定。
作为最后的介绍性示例,在前面的示例中使用的Inventor对象展示了布尔运算符的用法。
Expression exp = parser.parseExpression('name == #39;Nikola Tesla#39;');
boolean result = exp.getValue(context, Boolean.class); // evaluates to true
4.3.1 EvaluationContext接口
在进行表达式求值的过程中,解析属性、方法、字段或帮助执行类型转换时,可以使用EvaluationContext接口。作为现成的实现,StandardEvaluationContext使用反射机制来操作对象,缓存java.lang.reflect.Method,java.lang.reflect.Field以及 java.lang.reflect.Constructor实例,来提升性能。
使用StandardEvaluationContext,你可以指定使用setRootObject()方法进行求值的根对象,或是将根对象传入构造器。你还可以指定setVariable() 方法和 registerFunction()方法中将用到的变量和函数。变量和函数的使用参考章节4.5.11和4.5.12。你还可以在StandardEvaluationContext中注册自定义的ConstructorResolver、MethodResolver和PropertyAccessor,以此来扩展SpEL进行表达式求值的方式。详情请参考这些类的java文档。
类型转换
默认情况下,SpEL使用Spring core(org.springframework.core.convert.ConversionService)中提供的转换服务。这种转换服务附带了许多内置的转换器,可以进行常规转换,但也可以完全扩展,因此可以添加类型之间的自定义转换。此外,它支持泛型。这意味着,当在表达式中使用泛型类型时,SpEL将尝试转换以维护其遇到的任何对象的类型正确性。
这在实践中意味着什么?假设setValue()方法正在使用赋值来设置List属性。该属性的类型实际上是Listlt;Booleangt;。SpEL会认识到列表中的元素在被放入其中之前需要被转换为Boolean类型。一个简单的例子如下:
class Simple {
public Listlt;Booleangt; booleanList = new ArrayListlt;Booleangt;();
}
Simple simple = new Simple();
simple.booleanList.add(true);
StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple);
// false is passed in here as a string. SpEL and the conversion service will
// correctly recognize that it needs to be a Bo
全文共21049字,剩余内容已隐藏,支付完成后下载完整资料
资料编号:[14773],资料为PDF文档或Word文档,PDF文档可免费转换为Word
以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。