文字
在 EL 表达式中,数字、字符串、布尔值和 null
都可以被指定为文字值。字符串可以用单引号或双引号定界。布尔值被指定为 true
和 false
。
Taglib 伪指令
正如我们先前讨论的,JSTL 1.0 包括四个定制标记库。为了演示 JSTL 标记和表达式语言的交互,我们将研究几个来自 JSTL core
库的标记。和使用任何 JSP 定制标记库一样,必须在您想要使用这个库标记的任何页面中包括 taglib
伪指令。清单 7 显示了用于这个特定库的伪指令。
清单 7. 用于 JSTL core 库 EL 版本的 taglib 伪指令
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> |
实际上,对应于 JSTL core
库的 taglib
伪指令有两种,因为在 JSTL 1.0 中,EL 是可选的。所有四个 JSTL 1.0 定制标记库都有使用 JSP 表达式(而不是 EL)指定动态属性值的备用版本。因为这些备用库依赖于 JSP 的更传统的请求时属性值,所以它们被称为 RT 库,而那些使用表达式语言的则被称为 EL 库。开发人员用不同的 taglib
伪指令来区分每个库的这两个版本。清单 8 显示了使用 core 库的 RT 版本的伪指令。但是,由于现在我们讨论的重点是 EL,所以首先需要这些伪指令。
清单 8. 用于 JSTL core 库 RT 版本的 taglib 伪指令
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c_rt" %> |
变量标记
我们首先要考虑的 JSTL 定制标记是 <c:set>
操作。正如已经说明的,限制了作用域的变量在 JSTL 中起关键作用,<c:set>
操作提供基于标记的机制来创建和设置限制了作用域的变量。清单 9 中显示了该操作的语法,其中 var
属性指定了限制了作用域的变量的名称,scope
属性表明了该变量驻留在哪个作用域中,value
属性指定了分配给该变量的值。如果指定变量已经存在,则简单地将所指明的值赋给它。如果不存在,则创建新的限制了作用域的变量,并用该值初始化这个变量。
清单 9. <c:set> 操作的语法
<c:set var="name " scope="scope " value="expression "/> |
scope
属性是可选的,其缺省值是 page
。
清单 10 中显示了 <c:set>
的两个示例。在第一个示例中,将会话作用域变量设置成 String
值。在第二个示例中,用表达式来设置数值:将页面作用域内名为 square
的变量赋值为名为 x
的请求参数的值的平方。
清单 10. <c:set> 操作示例
<c:set var="timezone" scope="session" value="CST"/> |
您还可以将限制了作用域的变量的值指定为 <c:set>
操作的主体内容,而不是使用属性。使用这种方法,您可以重新编写清单 10 中的第一个示例,如清单 11 所示。此外,正如我们马上可以看到的,<c:set>
标记的主体内容本身也可以使用定制标记。<c:set>
主体内生成的所有内容都将作为一个 String
值赋给指定变量。
清单 11. 通过主体内容指定 <c:set> 操作的值
<c:set var="timezone" scope="session">CST</c:set> |
JSTL core 库包含第二个用于管理限制了作用域的变量的标记 ― <c:remove>
。顾名思义,<c:remove>
操作是用来删除限制了作用域的变量的,它获取两个属性。var
属性指定待删除变量的名称,scope
属性是可选的,它表示待删除变量来自哪个作用域,缺省为 page
,如清单 12 所示。
清单 12. <c:remove> 操作示例
<c:remove var="timezone" scope="session"/> |
输出
尽管 <c:set>
操作允许将表达式结果赋给限制了作用域的变量,但开发人员通常会希望只显示表达式的值,而不存储它。JSTL <c:out>
定制标记承担这一任务,其语法如清单 13 所示。该标记对由其 value
属性指定的表达式进行求值,然后打印结果。如果指定了可选属性 default
,那么,在对 value
属性的表达式求值所得结果为 null
或空 String
的情况下,<c:out>
将打印其值。
清单 13. <c:out> 操作的语法
<c:out value="expression " default="expression " escapeXml="boolean "/> |
escapeXml
属性也是可选的。它控制当用 <c:out>
标记输出诸如“<”、“>”和“&”之类的字符(在 HTML 和 XML 中具有特殊意义)时是否应该进行转义。如果将 escapeXml
设置为 true,则会自动将这些字符转换成相应的 XML 实体(此处提到的字符分别转换成 <
、>
和 &
)。
例如,假定有一个名为 user
的会话作用域变量,它是一个类的实例,该类为用户定义了两个特性:username
和 company
。每当用户访问站点时,这个对象被自动分配给会话,但直到用户实际登录后,才会设置这两个特性。假定是这种方案,请考虑清单 14 中的 JSP 片段。在用户登录之后,这个片段将显示单词“Hello”,其后是他/她的用户名和一个惊叹号。但是,在用户登录之前,由这个片段生成的内容则是短语“Hello Guest!”。在这种情况下,因为 username
特性还有待初始化,所以 <c:out>
标记将转而打印出 default
属性的值(即字符串“Guest”)。
清单 14. 带缺省内容的 <c:out> 操作示例
Hello <c:out value="${user.username}" default=="Guest"/>! |
接下来,考虑清单 15,它使用了 <c:out>
标记的 escapeXml
属性。如果在这种情况下已经将 company
特性设置成 Java String
值 "Flynn & Sons"
,那么,实际上该操作生成的内容将是 Flynn & Sons
。如果这个操作是生成 HTML 或 XML 内容的 JSP 页面的一部分,那么,这个字符串中间的“&”符号最终可能被解释为 HTML 或 XML 控制字符,从而妨碍了对该内容的显示或解析。但是,如果将 escapeXml
属性值设置成 true
,则所生成的内容将是 Flynn & Sons
。浏览器或解析器不会因在解释时遇到这种内容而出问题。假定 HTML 和 XML 是 JSP 应用程序中最常见的内容类型,所以 escapeXml
属性的缺省值是 true
就不足为奇了。
清单 15. 禁用转义的 <c:out> 操作示例
<c:out value="${user.company}" escapeXml=="false"/> |
用缺省值设置变量
除了简化动态数据的显示之外,当通过 <c:set>
设置变量值时,<c:out>
指定缺省值的能力也很有用。正如清单 11 所示,用来赋给限制了作用域的变量的值可以指定为 <c:set>
标记的主体内容,也可以通过其值属性来指定。通过将 <c:out>
操作嵌套在 <c:set>
标记的主体内容中,变量赋值就可以利用其缺省值能力。
清单 16 中说明了这种方法。外部 <c:set>
标记的行为非常简单:它根据其主体内容设置会话作用域 timezone
变量的值。但是,在这种情况下,主体内容是通过 <c:out>
操作生成的。这个嵌套操作的值属性是表达式 ${cookie['tzPref'].value}
,它尝试通过 cookie
隐式对象返回名为 tzPref
的 cookie 值。(cookie
隐式对象将 cookie 名称映射到相应的 Cookie
实例,这意味着必须通过对象的 value
特性使用点运算符来检索储存在 cookie 中的实际数据。)
清单 16. 合并 <c:set> 和 <c:out> 以提供缺省变量值
<c:set var="timezone" scope=="session"> |
但是,请考虑以下情况,用户是第一次尝试使用这段代码的 Web 应用程序。结果是,请求中没有提供名为 tzPref
的 cookie。这意味着使用隐式对象的查找将返回 null
,在这种情况下整个表达式将返回 null
。因为对 <c:out>
标记的 value
属性求值的结果是 null
,所以 <c:out>
标记会转而输出对其 default
属性求值的结果。在这里是字符串 CST
。因此,实际的结果是将 timezone
限制了作用域的变量设置成用户的 tzPref
cookie 中存储的时区,或者,如果没有,则使用缺省时区 CST
。
CST
。
|
|