因为 EL 标识符是作为隐式对象或限制了作用域的变量(通过属性来实现)解析的,因此有必要将它们转换成 Java 对象。EL 可以自动包装和解包其相应的 Java 类中的基本类型(例如,可以在后台将int
强制转换成 Integer
类,反之亦可),但大多数的标识符将成为指向完整的 Java 对象的指针。
结果是,对这些对象的特性或(在对象是数组和集合的情况下)对其元素的访问通常是令人满意的。就为了实现这种用途,EL 提供了两种不同的存取器(点运算符(.
)和方括号运算符([]
)),也支持通过 EL 操作特性和元素。
点运算符通常用于访问对象的特性。例如,在表达式 ${user.firstName}
中,使用点运算符来访问 user
标识符所引用对象的名为firstName
的特性。EL 使用 Java bean 约定访问对象特性,因此必须定义这个特性的 getter 方法(通常是名为 getFirstName()
的方法),以便表达式正确求值。当被访问的特性本身是对象时,可以递归地应用点运算符。例如,如果我们虚构的 user
对象有一个实现为 Java 对象的address
特性,那么也可以用点运算符来访问这个对象的特性。例如,表达式 ${user.address.city}
将会返回这个地址对象嵌套的city
特性。
方括号运算符用来检索数组和集合的元素。在数组和有序集合(也即,实现了 java.util.List
接口的集合)的情况下,把要检索的元素的下标放在方括号中。例如,表达式${urls[3]}
返回 urls
标识符所引用的数组或集合的第四个元素(和 Java 语言以及 JavaScript 中一样,EL 中的下标是从零开始的)。
对于实现 java.util.Map
接口的集合,方括号运算符使用关联的键查找存储在映射中的值。在方括号中指定键,并将相应的值作为表达式的值返回。例如,表达式${commands["dir"]}
返回与 commands
标识符所引用的 Map
中的"dir"
键相关联的值。
对于上述两种情况,都可允许表达式出现在方括号中。对嵌套表达式求值的结果将被作为下标或键,用来检索集合或数组的适当元素。和点运算符一样,方括号运算符也可以递归应用。这使得 EL 能够从多维数组、嵌套集合或两者的任意组合中检索元素。此外,点运算符和方括号运算符还可以互操作。例如,如果数组的元素本身是对象,则可以使用方括号运算符来检索该数组的元素,并结合点运算符来检索该元素的一个特性(例如${urls[3].protocol}
)。
假定 EL 充当指定动态属性值的简化语言,EL 存取器有一个有趣的功能(与 Java 语言的存取器不同),那就是它们在应用于 null
时不抛出异常。如果应用 EL 存取器的对象(例如,${foo.bar}
和${foo["bar"]}
中的 foo
标识符)是 null
,那么应用存取器的结果也是null
。事实证明,在大多数情况下,这是一个相当有用的行为,不久您就会了解这一点。
最后,点运算符和方括号运算符可能实现某种程度的互换。例如,也可以使用 ${user["firstName"]}
来检索 user
对象的 firstName
特性,正如可以用 ${commands.dir}
获取与 commands
映射中的 "dir"
键相关联的值一样。
EL 还可以通过使用标识符和存取器,遍历包含应用程序数据(通过限制了作用域的变量公开)或关于环境的信息(通过 EL 隐式对象)的对象层次结构。但是,只是访问这些数据,通常不足以实现许多 JSP 应用程序所需的表示逻辑。
最终,EL 还包括了几个用来操作和比较 EL 表达式所访问数据的运算符。表 2 中汇总了这些运算符。
类别 | 运算符 |
算术运算符 | + 、- 、* 、/ (或 div )和% (或 mod ) |
关系运算符 | == (或 eq )、!= (或 ne )、< (或lt )、> (或 gt )、<= (或 le )和>= (或 ge ) |
逻辑运算符 | && (或 and )、|| (或 or )和 ! (或 not ) |
验证运算符 | empty |
算术运算符支持数值的加法、减法、乘法和除法。还提供了一个求余运算符。注:除法和求余运算符都有替代的、非符号的名称(为的是与 XPath 保持一致)。清单 5 中显示了一个演示算术运算符用法的示例表达式。对几个 EL 表达式应用算术运算符的结果是将该算术运算符应用于这些表达式返回的数值所得的结果。
${item.price * (1 + taxRate[user.address.zipcode])}
关系运算符允许比较数字或文本数据。比较的结果作为布尔值返回。逻辑运算符允许合并布尔值,返回新的布尔值。因此,可以将 EL 逻辑运算符应用于嵌套的关系或逻辑运算符的结果,如清单 6 所示。
${(x >= min) && (x <= max)}
最后一种 EL 运算符是 empty
,它对于验证数据特别有用。empty
运算符采用单个表达式作为其变量(也即,${empty input}
),并返回一个布尔值,该布尔值表示对表达式求值的结果是不是“空”值。求值结果为null
的表达式被认为是空,即无元素的集合或数组。如果参数是对长度为零的 String
求值所得的结果,则 empty
运算符也将返回 true
。
表 3 显示了 EL 运算符的优先级。正如清单 5 和 6 所示,可以用圆括号对表达式分组,高于普通的优先级规则。
[] , . |
() |
unary - 、not 、! 、empty |
* 、/ 、div 、% 、mod |
+ 、binary - |
() <</code> 、> 、<= 、>= 、lt 、gt 、le 、ge |
== 、!= 、eq 、ne |
&& 、and |
|| 、or |