jinlibing 发表于 2013-1-27 06:24:23

jstl 入门-------IBM

                                     http://www.ibm.com/i/c.gif
            developerWorks 中国  >  Java technology  >http://www.ibm.com/i/c.gif
            JSTL 入门: 表达式语言

            通过避免使用脚本编制元素来简化对 JSP 应用程序的软件维护
            http://www.ibm.com/i/c.gif            http://www-128.ibm.com/developerworks/cn/i/dw.gif                                  http://www.ibm.com/i/c.gif                                                                                    http://www.ibm.com/i/c.gif                                                                                                                                                文档选项                                                                                                                                                                                                                                              <noscript></noscript>                                                                                                                                                                                                                http://www.ibm.com/i/c.gif                                                http://www.ibm.com/i/v14/icons/em.gif                                                                                                将此页作为电子邮件发送
                                                                                                                                                                                                                                                                                  <!----><!---->
                                                                                                                        拓展 Tomcat 应用                                                                                                                                                                                                                                                                                                                                                                                  http://www.ibm.com/i/c.gif                                                http://www.ibm.com/i/v14/icons/fw_bold.gif                                                                                                下载 IBM 开源 J2EE 应用服务器 WAS CE 新版本 V1.1
                                                                                                                                                                                                                                                                                                                    <!---->
                                                                                  级别: 初级
            Mark A. Kolb, 软件工程师
            
            2003 年 5 月 27 日
            JSP 标准标记库(JSP Standard Tag Library,JSTL)是一个实现 Web 应用程序中常见的通用功能的定制标记库集,这些功能包括迭代和条件判断、数据管理格式化、XML 操作以及数据库访问。在 developerWorks 上其新系列的第一篇文章中,软件工程师 Mark Kolb 向您展示了如何使用 JSTL 标记来避免在 JSP 页面中使用脚本编制元素。您还将了解如何通过从表示层删除源代码来简化软件维护。最后,您将了解 JSTL 经过简化的表达式语言,它允许在不必使用功能齐全的编程语言的情况下对 JSTL 操作指定动态属性值。<!----><!----><!---->            JavaServer Pages(JSP)是用于 J2EE 平台的标准表示层技术。JSP 技术提供了用于执行计算(这些计算用来动态地生成页面内容)的脚本编制元素和操作。脚本编制元素允许在 JSP 页面中包括程序源代码,在为响应用户请求而呈现页面时可以执行这些源代码。操作将计算操作封装到很象 HTML 或 XML 标记的标记中,JSP 页面的模板文本通常包含这些标记。JSP 规范只将几种操作定义成了标准,但从 JSP 1.1 开始,开发人员已经能够以定制标记库的方式创建其自己的操作了。
            JSP 标准标记库(JSTL)是 JSP 1.2 定制标记库集,这些标记库实现大量服务器端 Java 应用程序常用的基本功能。通过为典型表示层任务(如数据格式化和迭代或条件内容)提供标准实现,JSTL 使 JSP 作者可以专注于特定于应用程序的开发需求,而不是为这些通用操作“另起炉灶”。
            当然,您可以使用 JSP 脚本编制元素(scriptlet、表达式和声明)来实现此类任务。例如,可以使用三个 scriptlet 实现条件内容,清单 1 中着重显示了这三个 scriptlet。但是,因为脚本编制元素依赖于在页面中嵌入程序源代码(通常是 Java 代码),所以对于使用这些脚本编制元素的 JSP 页面,其软件维护任务的复杂度大大增加了。例如,清单 1 中的 scriptlet 示例严格地依赖于花括号的正确匹配。如果不经意间引入了一个语法错误,则条件内容中的嵌套其它 scriptlet 可能会造成严重破坏,并且在 JSP 容器编译该页面时,要使所产生的错误信息有意义可能会很困难。
            
            JSTL 1.0</p>            JSTL 1.0 发布于 2002 年 6 月,由四个定制标记库( core 、 format 、 xml 和 sql )和一对通用标记库验证器( ScriptFreeTLV 和 PermittedTaglibsTLV )组成。 core 标记库提供了定制操作,通过限制了作用域的变量管理数据,以及执行页面内容的迭代和条件操作。它还提供了用来生成和操作 URL 的标记。顾名思义, format 标记库定义了用来格式化数据(尤其是数字和日期)的操作。它还支持使用本地化资源束进行 JSP 页面的国际化。 xml 库包含一些标记,这些标记用来操作通过 XML 表示的数据,而 sql 库定义了用来查询关系数据库的操作。
            两个 JSTL 标记库验证器允许开发人员在其 JSP 应用程序中强制使用编码标准。可以配置 ScriptFreeTLV 验证器以在 JSP 页面中禁用各种类型的 JSP 脚本元素 ― scriptlet、表达式和声明。类似地, PermittedTaglibsTLV 验证器可以用来限制可能由应用程序的 JSP 页面访问的定制标记库集(包括 JSTL 标记库)。
            尽管 JSTL 最终将会成为 J2EE 平台的必需组件,但目前只有少数应用程序服务器包括它。JSTL 1.0 的参考实现可作为 Apache 软件基金会(Apache Software Foundation)的 Jakarta Taglibs 项目(请参阅 参考资料)的一部分而获得。可以将该参考实现中的定制标记库合并到任何支持 JSP 1.2 和 Servlet 2.3 规范的服务器,以添加对 JSTL 的支持。
            
                                                                        http://www.ibm.com/i/v14/rules/blue_rule.gif
                        http://www.ibm.com/i/c.gif                                                                                                                      http://www.ibm.com/i/c.gif
                                                                                                                        http://www.ibm.com/i/v14/icons/u_bold.gif
                                                                        回页首                                                                                                                                                                    
            
            限制了作用域的变量
            JSP API 通过 <jsp:useBean> 操作允许从 JSP 容器内的四个不同作用域中存储和检索数据。JSTL 通过提供用于指定和除去这些作用域中的对象的附加操作来扩展这一能力。此外,EL 提供将这些对象作为限制了作用域的变量进行检索的内置支持。特别地,任何出现在 EL 表达式中但不对应于任何 EL 隐式对象的标识符,都被自动假定为引用存储在四个 JSP 作用域的其中某个中的对象,这四个作用域是:
            
               
[*]页面作用域               
[*]请求作用域               
[*]会话作用域               
[*]应用程序作用域            
            您可能还记得,只有在为特定请求处理页面期间才能检索存储在该页面作用域中的对象。如果对象是存储在请求作用域中的,可以在处理所有参与处理某请求的页面期间检索这些对象(譬如在对某个请求的处理中遇到了一个或多个 <jsp:include> 或 <jsp:forward> 操作)。如果对象是存储在会话作用域中的,则在与 Web 应用程序的交互式会话期间,可以由用户访问的任何页面检索它(即,直到与该用户交互相关联的 HttpSession 对象无效为止)。可以由任何用户从任何页面访问存储在应用程序作用域中的对象,直到卸载 Web 应用程序本身为止(通常是由于关闭 JSP 容器所致)。
            通过将字符串映射为期望作用域中的对象来将对象存储到该作用域。然后,就可以通过提供相同字符串来从该作用域检索该对象。在作用域的映射中查找字符串,并返回被映射的对象。在 Servlet API 中,将此类对象称为相应作用域的 属性。但是,在 EL 的上下文中,也将与属性相关联的字符串看作变量的名称,该变量通过属性映射的方式获得特定的值。
            在 EL 中,与隐式对象无关联的标识符被认为是存储在四个 JSP 作用域中的名称对象。首先对页面作用域检查是否存在这样的标识符,其次对请求作用域、然后对会话作用域、最后对应用程序作用域依次进行这样的检查,然后测试该标识符的名称是否与存储在该作用域中的某个对象的名称匹配。第一个这样的匹配作为 EL 标识符的值被返回。通过这种方法,可以将 EL 标识符看作引用限制了作用域的变量。
            从更技术的方面来说,没有映射到隐式对象的标识符是用 PageContext 实例的 findAttribute() 方法求值的,该实例表示对页面的处理,在该页面上,当前正在处理用于请求的表达式。标识符的名称作为参数传递给这个方法,然后该方法依次在四个作用域中搜索具有相同名称的属性。并将所找到的第一个匹配项作为 findAttribute() 方法的值返回。如果未在这四个作用域中找到这样的属性,则返回 null 。
            最终,限制了作用域的变量是四个 JSP 作用域的属性,这些属性具有可以用作 EL 标识符的名称。只要对限制了作用域的变量赋予由字母数字组成的名称,就可以通过 JSP 中提供的用于设置属性的任何机制来创建它们。这包括内置的 <jsp:useBean> 操作,以及由 Servlet API 中的几个类定义的 setAttribute() 方法。此外,四个 JSTL 库中定义的许多定制标记本身就能够设置作为限制了作用域的变量使用的属性值。
            
                                                                        http://www.ibm.com/i/v14/rules/blue_rule.gif
                        http://www.ibm.com/i/c.gif                                                                                                                      http://www.ibm.com/i/c.gif
                                                                                                                        http://www.ibm.com/i/v14/icons/u_bold.gif
                                                                        回页首                                                                                                                                                                    
            
            存取器
            因为 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} 返回 urls 标识符所引用的数组或集合的第四个元素(和 Java 语言以及 JavaScript 中一样,EL 中的下标是从零开始的)。
            对于实现 java.util.Map 接口的集合,方括号运算符使用关联的键查找存储在映射中的值。在方括号中指定键,并将相应的值作为表达式的值返回。例如,表达式 ${commands["dir"]} 返回与 commands 标识符所引用的 Map 中的 "dir" 键相关联的值。
            对于上述两种情况,都可允许表达式出现在方括号中。对嵌套表达式求值的结果将被作为下标或键,用来检索集合或数组的适当元素。和点运算符一样,方括号运算符也可以递归应用。这使得 EL 能够从多维数组、嵌套集合或两者的任意组合中检索元素。此外,点运算符和方括号运算符还可以互操作。例如,如果数组的元素本身是对象,则可以使用方括号运算符来检索该数组的元素,并结合点运算符来检索该元素的一个特性(例如 ${urls.protocol} )。
            假定 EL 充当指定动态属性值的简化语言,EL 存取器有一个有趣的功能(与 Java 语言的存取器不同),那就是它们在应用于 null 时不抛出异常。如果应用 EL 存取器的对象(例如, ${foo.bar} 和 ${foo["bar"]} 中的 foo 标识符)是 null ,那么应用存取器的结果也是 null 。事实证明,在大多数情况下,这是一个相当有用的行为,不久您就会了解这一点。
            最后,点运算符和方括号运算符可能实现某种程度的互换。例如,也可以使用 ${user["firstName"]} 来检索 user 对象的 firstName 特性,正如可以用 ${commands.dir} 获取与 commands 映射中的 "dir" 键相关联的值一样。
            
                                                                        http://www.ibm.com/i/v14/rules/blue_rule.gif
                        http://www.ibm.com/i/c.gif                                                                                                                      http://www.ibm.com/i/c.gif
                                                                                                                        http://www.ibm.com/i/v14/icons/u_bold.gif
                                                                        回页首                                                                                                                                                                    
            
            文字
            在 EL 表达式中,数字、字符串、布尔值和 null 都可以被指定为文字值。字符串可以用单引号或双引号定界。布尔值被指定为 true 和 false 。
            
                                                                        http://www.ibm.com/i/v14/rules/blue_rule.gif
                        http://www.ibm.com/i/c.gif                                                                                                                      http://www.ibm.com/i/c.gif
                                                                                                                        http://www.ibm.com/i/v14/icons/u_bold.gif
                                                                        回页首                                                                                                                                                                    
            
            变量标记
            我们首先要考虑的 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 var="square" value="${param['x'] * param['x']}"/>                                                                                  
            您还可以将限制了作用域的变量的值指定为 <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"/>                                                                                  
            
                                                                        http://www.ibm.com/i/v14/rules/blue_rule.gif
                        http://www.ibm.com/i/c.gif                                                                                                                      http://www.ibm.com/i/c.gif
                                                                                                                        http://www.ibm.com/i/v14/icons/u_bold.gif
                                                                        回页首                                                                                                                                                                    
            
            输出
            尽管 <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"/>                                                                                  
            
                                                                        http://www.ibm.com/i/v14/rules/blue_rule.gif
                        http://www.ibm.com/i/c.gif                                                                                                                      http://www.ibm.com/i/c.gif
                                                                                                                        http://www.ibm.com/i/v14/icons/u_bold.gif
                                                                        回页首                                                                                                                                                                    
            
            用缺省值设置变量
            除了简化动态数据的显示之外,当通过 <c:set> 设置变量值时, <c:out> 指定缺省值的能力也很有用。正如 清单 11 所示,用来赋给限制了作用域的变量的值可以指定为 <c:set> 标记的主体内容,也可以通过其值属性来指定。通过将 <c:out> 操作嵌套在 <c:set> 标记的主体内容中,变量赋值就可以利用其缺省值能力。
            清单 16 中说明了这种方法。外部 <c:set> 标记
页: [1]
查看完整版本: jstl 入门-------IBM