尽管 <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">
<c:out value="${cookie['tzPref'].value}" default=="CST"/>
</c:set>
但是,请考虑以下情况,用户是第一次尝试使用这段代码的 Web 应用程序。结果是,请求中没有提供名为 tzPref
的 cookie。这意味着使用隐式对象的查找将返回null
,在这种情况下整个表达式将返回 null
。因为对 <c:out>
标记的 value
属性求值的结果是 null
,所以 <c:out>
标记会转而输出对其 default
属性求值的结果。在这里是字符串CST
。因此,实际的结果是将 timezone
限制了作用域的变量设置成用户的 tzPref
cookie 中存储的时区,或者,如果没有,则使用缺省时区CST
。
EL 和 JSP 2.0目前,表达式语言仅可用于指定 JSTL 定制标记中的动态属性值。但 JSTL 1.0 表达式语言的一个扩展已经被提出,会把它包括到 JSP 2.0 中去,眼下正在进行最后评审。这个扩展将允许开发人员通过自己的定制标记来使用 EL。页面作者将可以在目前允许使用 JSP 表达式的任何地方使用 EL 表达式,譬如将动态值插入模板文本中:<p>Your preferred time zone is ${timezone}</p>。
这个 JSP 2.0 功能(就象 JSTL 本身一样)将支持页面作者进一步减少对 JSP 编制脚本元素的依赖,从而改进 JSP 应用程序的可维护性。