标准标签库 JSTL 的全名为 Java Server Pages Standard Tag Library。它是由 JCP( Java CommnunityProcess)所指定的标准规范,它主要是给 Java Web 开发者提供了一个标准的通用标签库。通过 JSTL,可以部分地取代传统 JSP 程序中嵌入 Java 代码的做法,可以使得 JSP 页面程序的风格趋于统一,并且容易维护。 从 JSP1.1 规范开始就开发支持在 JSP 文件中使用自定义标签了,就是因为自定义标签的广泛使用,从而使得大量的同功能标签不断地重复定义,为了减少对解决类似通用问题的独立标记库的需求,在Java Community Process( JSR 52)的赞助下创建了 JSTL( JavaServer Pages Standard Tag Library, JSTL)标准标记库,为解决这些通用功能提供一个单一的标准解决方案。 JSTL 是一个开放源代码的 JSP 标签库,并且还在不断地完善过程中。 JSTL 特别为条件处理、迭代、国际化、数据库访问和可扩展标记语言( XML)处理提供支持。 JSTL 还引入了 expression language( EL,表达式语言),极大地简化了对 JSP 中应用数据的访问和操作。 JSTL 至今主要为开发者提供了如下五大类的标签库:
核心标签库:为日常任务提供通用支持,如显示和设置变量、重复使用一组项目、测试条件以及其他操作(如导入和重定向 Web 页面等)。国际化( I18N)标签库:支持多国语种的应用程序。 SQL 标签库:对访问和修改数据库提供标准化支持。 XML 标签库:对 XML 文件处理和操作的支持,包括 XML 节点的解析、迭代、基于 XML 数据的条件评估以及可扩展样式语言转换( Extensible Style Language Transformations, XSLT)的执行。函数标签库:通过在 EL 表达式中调用函数标签库中的函数来实现特定的操作。例如${fn:contains(string, substring)},判断 string 字符串中是否包含 substring 字符串。展示了各标签库的使用方法:
标签库URI前缀使用模式核心标签库http://java.sun.com/jstl/corec<c:tagname…>国际化( I18N)标签库http://java.sun.com/jstl/fmtfmt<fmt:tagname…>SQL标签库http://java.sun.com/jstl/sqlsql<sql:tagname…>XML标签库http://java.sun.com/jstl/xmlx<x:tagname…>函数标签库http://java.sun.com/jstl/functionsfnfn:functionName()具体配置和引入方式可参考:JSTL配置&pom配置 JSTL(标准标签库)的使用对 JSP/servlet 开发者来说是一个重大的进展,因为它存在很多的优点,并且很有可能在不久的将来成为实现动态、基于 Java 站点的一个主要方法。概括起来, JSTL 主要的优点如下:
在所有的应用服务器之间提供了一致的接口程序,这样可以最大程度地提供 Web 应用程序在各种应用服务器之间的可移植性。简化了 JSP 的 Web 应用系统的开发,并且使得 JSP 页面的编程风格统一、易于维护。大量使用 JSTL 提供的逻辑操作(例如迭代、判断,甚至数据库访问),可以大大减少 JSP 中脚本代码( Scriptlets)的数量,甚至可以没有任何脚本代码就可以实现其大部分动态效果。运行 JSP 设计工具与 Web 应用程序开发的进一步集成,虽然现在支持 JSTL 开发的 IDE 开发工具还没有出现(或者正是由于这个原因,使得 JSTL 还不这么流行),但是可以相信不久就会有支持JSTL 的开发工具出现。JSTL 已经封装了 JSP 中很多常用的功能,比如,可以使用 JSTL 中的标签来进行迭代输出某个 List或者 Set 集合类。 注意:由于从 JSP1.1 规范才开始支持 JSP 中的自定义标签,所以 JSTL 需要运行在支持 JSP1.2 和Servlet2.3 规范的容器上,比如 Tomcat4.x 和 Tomcat5.x 服务器。
注:下面只列举出主要的知识点,详细的会链接到<菜鸟教程>,当然也可以直接参考菜鸟教程。而且下面讲述的都是在已经配置好JSTL环境的条件下进行的。
注:在JSTL标签中运用到了EL表达式,像${}这样的语法,了解EL表达式可以参考:EL表达式—学习笔记
核心标签是最常用的JSTL标签,引用核心标签库的语法如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>分类:
表达式操作标签:表达式操作标签包括 out、 set、 remove 和 catch流程控制标签:用于流程控制的标签,其中包括: if、 choose、 when 与 otherwise 等URL相关的标签:与 URL 相关的标签主要是用来将其他文件包含进来,或者提供页面之间的重定位以及 URL 地址的生成、参数的输出等等。包括如下几个标签 <c:import>标签:与传统 JSP 页面中的<jsp:include>标记相类似<c:redirect>标签:进行页面的重定位<c:url>:主要是用来重写 URL 地址<c:param>:一般 param 标签会和别的标签一起配套使用,用于参数值的传递使用<c:catch>标签,其只有一个var属性,用来储存错误信息的变量。其中包含异常以及异常的解释信息,如果我们只想查看异常的解释信息,则可以使用var指定的变量.message即可。
<c:import>和 <jsp:include> 一样, <c:import> 也是一种请求时操作,它 的基本任务就是将其它一些 Web 资源的内容插入 JSP 页面中。
JSTL格式化标签用来格式化并输出文本、日期、时间、数字。引用格式化标签库的语法如下:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>JSTL 标准标签库对国际化问题提供了很好的支持,其中用于支持国际化和本地化开发的标签包括:
<fmt:setLocale>:用于设置当前本地化环境,其实为对应的 Java 类 javax.servlet.jsp.jstl.fmt.locale配置参数值,这个指定的参数由 JSP 运行时维护,用于确定各个 JSTL 标记使用的本地化环境。<fmt:bundle>:指定消息资源使用的文件。<fmt:message>:显示消息资源文件中指定 key 的消息,支持带参数消息。<fmt:param>:给带参数的消息设置参数值。<fmt:setBundle>:设置消息资源文件。HTML 请求到达服务器时,浏览器提供的 HTTP 首部可以指出用户的首选本地化环境(可能是多个本地化环境的列表)。这个列表放在 Accept-Language HTTP 首部中。 JSP 容器会访问这个首部信息,如果没有使用标签<fmt:setLocale>明确地指定应用本地化环境, JSTL 标记就会使用这个列表中的首选本地化环境。 遗憾的是,用这种方法来确定用户想用的本地化环境极不可靠,原因如下:
不同的浏览器会以不同的方式配置首选本地化环境列表。大多数用户从来都不配置浏览器的首选本地化环境。有些用户可能想使用另外某个本地化环境访问页面,而不是所配置的首选本地化环境。有些用户可能会打开多个浏览器窗口(当前所有浏览器都支持这一点),并希望每个浏览器窗口使用不同的本地化环境。由于存在这些不可控的因素,建议还是要求用户明确地指定想用什么本地化环境。
一旦已经设置了 Web 应用的本地化环境之后,就可以使用<fmt:bundle>标记了,其体中可以包括一些调用本地化文本的<fmt:message>标签。当 <fmt:bundle> 标 签 体 中 嵌 套 <fmt:message> 标 签 时 , 这 时 <fmt:message> 标 签 默 认 就 是 使 用 <fmt:bundle>标签中 basename 所指定的资源文件。
该标签用于显示本地化的文本,它通过 key 属性来取得资源文件中相应的消息。
该标签用于设置一个资源文件,并给定一个标记,以便可以通过在<fmt:message>标签中指定 bundle属性值来取得这个资源文件中的消息。该标签与<fmt:bundle>标签功能相类似,只是<fmt:bundle>标签一般在体中嵌套使用<fmt:message>,而<fmt:setBundle>标签用来先定义一个资源文件,并给它指定一个变量,以便在后面通过这个变量来单独使用<fmt:message>标签获取资源文件中的消息。
该标签一般和<fmt:message>标签配套使用,用来给获取的消息中插入一个值。
<1>创建资源文件
res_zh_CN.properties 资源文件:中文的资源文件,基名为 resres_en_US.properties 资源文件:对应的英文资源文件app_zh_CN.properties 资源文件:中文的资源文件app_en_US.properties 资源文件:对应的英文资源文件,基名为 appapp_en_US.properties
avocation=playing basketball and reading courseMark=chinese{0}, math{1}, english{2} currentTime=The current time is {0}app_zh_CN.properties
avocation=\u7BEE\u7403\u3001\u9605\u8BFB courseMark=\u8BED\u6587{0}\u3001\u6570\u5B66{1}\u3001\u82F1\u8BED{2} currentTime=\u73B0\u5728\u65F6\u95F4\u4E3A{0}res_en_US.properties
gender=male name=Wang Xiaogang school=Peking Universityres_zh_CN.properties
gender=\u7537 name=\u738B\u5C0F\u521A school=\u5317\u4EAC\u5927\u5B66注:这些文件需要出现在classes 编译目录中,如果是IDE的话直接放到与源代码一起的地方就可以了,也就是源目录中。<2> 创建 selectLocale.jsp 语言选择页面
<h4>选择所要显示的语言</h4> <form action="fmt.jsp" method="get"> <select name="locale"> <option value="zh_CN">中文</option> <option value="en_US">English</option> </select> <input type="submit" value="提交"> </form><3> 创建 fmt.jsp 国际化显示页面 根据上一页面选择的语言来设置本地化环境,然后读取相应的资源文件中的消息,从而实现程序代码的国际化和本地化。该页面的详细代码如下:
<body> <c:set var="loc" value="${param.locale}" /> <!-- 设置本地化环境 --> <fmt:setLocale value="${loc}" /> <!--bundle体中取得资源消息 --> <br> <fmt:bundle basename="cn.jstl.res"> <fmt:message key="name" /> <br> <fmt:message key="gender" /> <br> <fmt:message key="school" /> <br> </fmt:bundle> <!--setBundle定义资源,再由message获得消息--> <br> <fmt:setBundle basename="cn.jstl.app" var="appBundle" /> <fmt:message key="avocation" bundle="${appBundle}" /> <br> <!--message标签体中使用param标签--> <br> <jsp:useBean id="now" class="java.util.Date" /> <fmt:formatDate value="${now}" type="both" var="currentDateString" /> <fmt:parseDate value="${currentDateString}" type="both" var="currentDate" /> <fmt:message key="currentTime" bundle="${appBundle}"> <fmt:param value="${currentDate}" /> </fmt:message> <br> <fmt:message key="currentTime" bundle="${appBundle}"> <fmt:param value="${currentDateString}" /> </fmt:message> <br> <!--message标签体中使用多个param标签--> <br> <fmt:message key="courseMark" bundle="${appBundle}"> <fmt:param value="${85}" /> <fmt:param value="${90}" /> <fmt:param value="${75}" /> </fmt:message> </body>注:需要导入核心标签库库和国际化标签库。
程序说明:
首先使用<c:set var="loc" value="${param.locale}" />来获取到上一页面中传递过来的 locale 参数值,并把它保存在 loc 变量中。<fmt:setLocale value="${loc}" />设置了本地化的语言环境。这里的 loc 变量为 zh_CN 或者en_US。该程序首先由<fmt:bundle>和<fmt:message>标签组合获取基名为 res 的资源文件中的消息。然后通过<fmt:setBundle>标签首先定一个基名为 app 的资源文件,并给这个资源文件一个appBundle 的标记。然后<fmt:message>标签通过这个标记来获取相应资源文件中的消息。< fmt:formatDate value="${now}" type="both" var="currentDateString"/>语句把时间 now 转化为本地化的格式显示,并把它保存在 currentDateString 变量中。 <fmt:parseDate value="${currentDateString}" type="both" var="currentDate"/>是把本地化的时间显示格式换另一种显示方式。在<fmt:message>标签中可以嵌套多个<fmt:param>标签来把相应的多个参数插入到要获取的消息中。效果图如下:
创建fmt_currency.jsp ,如下:
<body> <h3>Currency Formatting and locale:</h3> <hr> <!--中文,中国显示格式--> <h5>Chinese, China</h5> <fmt:setLocale value="zh_CN" /> <fmt:formatNumber type="currency" value="80000" /><br/> <!--英语,英国显示格式--> <h5>English, Great Britain</h5> <fmt:setLocale value="en_GB" /> <fmt:formatNumber type="currency" value="80000" /><br/> <fmt:formatNumber type="currency" value="80000" currencyCode="EUR"/><br/> <!--英语,美国显示格式--> <h5>English, USA</h5> <fmt:setLocale value="en_US" /> <fmt:formatNumber type="currency" value="80000" /><br/> </body>注:需要导入核心标签库库和国际化标签库。 程序说明:
本页面根据设置的本地化环境显示了三种不同的货币输出格式。currencyCode 属性的值必须是 ISO-4217 货币代码。货币代码都是三字母代码(均大写),可以在 unece.org/cefact/rec/cocucod.htm 找到完整的货币代码表。不过,并非所有货币代码在所有本地化环境中都得到支持,是否支持很大程度上取决于所用的 Java 2 平台实现。注:需要导入核心标签库库和国际化标签库。 程序说明:
在本程序中除了设置一个本地化环境外,在输出时间之前还有一点很重要,就是要为用户设置一个时区。如果应用可能在国际范围内访问,那么只采用服务器本身的时区来生成时间通常是没有意义的。理想情况下,应当也由用户来选择时区,具体方式与选择本地化环境类似。在这个例子中,时区设置为东部标准时间。就是使用 JSTL 的<fmt:timeZone>标签完成的,其中 value 属性指定一个地区 ID。代码中使用标准<jsp:useBean>动作创建了 java.util.Date 类的一个 JavaBean 实例,并用这个实例访问当前时间(服务器上的当前时间)。注意这个实例赋给了一个名为 currentTime 的 page 作用域变量。JSTL SQL标签库提供了与关系型数据库(Oracle,MySQL,SQL Server等等)进行交互的标签。引用SQL标签库的语法如下:
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>用于数据库操作的主要标签包括如下:
<sql:setDataSource>:该标签用于数据库连接设置。<sql:transaction>:把其他<sql:query>以及<sql:update>操作放置在一个事务中。<sql:query>:进行数据库查询操作。<sql:update>:进行数据库更新操作。<sql:param>:进行参数的设定。<sql:dateParam>:进行日期型参数的设置。JSTL XML标签库提供了创建和操作XML文档的标签。引用XML标签库的语法如下:
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>XML 提供了非常灵活的方式来表示结构化的数据,可以创建自己的标记来识别数据,不仅仅人可以看懂,而且计算机也可以读懂。并且 XML 可以在不兼容的系统之间进行数据的交换,所以 XML 必定将称为最普遍的数据操作和数据传输的工具。这也注定它能成为 Web 应用程序中极具引力的集成技术之一。
JSTL 标准标签库已经提供了一些关于 XML 操作的标签,使得 JSP 开发者可以在不深入了解 SAX( Simple API for XML)和 DOM( Document Object Model,即文件对象模式)等技术条件就可以处理XML 文件。 JSTL 主要提供了如下多种类型的标签来处理 XML 文件:
XML 核心动作 <x.parse>:用于解析 XML 文件<x.out>:通过 XPath 来读取 XML 文件中的某元素<x:set>:该标签用来计算 XPath 表达式,并且把结果保存在指定的变量当中XML 流程控制动作 <x:if><x:choose><x:when><x:otherwise><x:forEach>XML 转换动作 <x:transform>:用于把 XML 文件转换成 XSLT 格式<x:param>:和<x:transform>配套使用,用于传递参数在 XML 操作过程,一般先实现<c:import>标签把要处理的 XML 文件检索到,然后再使用<x:parse>标签来解析这个文件, <x:parse>标签支持标准的 XML 解析技术,例如文件对象模式( DOM)和简单的XML API( SAX)技术。还有标签<x:transform>标签可以使用来转换 XML 文件,它使用的是扩展样式语言( Extensible Stylesheet Language,简称 XSL)技术。关于 XML 的标签库还提供了很多标签来处理解析后的 XML 数据,其中就使用到了一种标准――XML 路径语言( XML Path Language, XPath),用来引用和读取解析后的 XML 文件中的数据。
XPath 标准是用来对 XML 文档各部分数据进行定位的语言。它除了提供了一套定位语法之外,还包括一些函数,可以提供基本的数字运算、布尔运算以及字符串处理等功能。 XPath 使用了一种紧凑和非 XML 的语法来方便地实现 XPath 在 XML 属性值中使用,它基于 XML文档的逻辑结构,在该结构中进行导航。除了用于定位, XPath 自身还包含了一个子集用于进行匹配,还可以用来验证一个节点是否匹配某个模式。 XPath 是把一个 XML 文档看成一个树和节点的模式。节点的类型可以有多种,其中包括元素节点、属性节点和文本节点。 XPath 的基本语法由表达式构成。在计算机表达式的值后面生成一个对象,这个对象有以下四种基本类型:
节点集( Node Set)布尔数值数字型字符串类型XPath 基本上和文件系统中查找文件相类似,如果路径是以“ /”开头的,则表示该路径是一个决定路径,这和在 UNIX 操作系统中关于文件路径的定义是一致的。 当然了 XPath 它本身有自己的一套完整的语法说明来进行 XML 文件的定位。这里不列出所有严格的定义表达式,而是使用一些实例来说明如何使用 XPath 语言。
下面是一个 XML 文件:
<authors> <author> <name>Zou Hai</name> <nationality>China</nationality> </author> <author period="”classical”"> <name>Johnson</name> <nationality>French</nationality> </author> <author> <name>Kitten</name> <nationality>German</nationality> </author> <super-author> <name>Chen Yong</name> <nationality>China</nationality> </super-author> </authors><1> 关于“ /”和“ //”的使用 “ /”是表示当前文档的节点,类似 DOS 目录分割符,“ //”则表示当前文档所有的节点。类似查看整个目录。
/authors/author:表示选择根目录下、父节点为 authors 的元素“ author”。 /authors/author/name:表示查找到所有名称为“ name”的元素,但是它的父节点为“ author”,而“ author”的父节点又为“ authors”。 //name:表示查找 XML 文件中的所有“ name”元素,而无论这个元素在什么层次。<2> 关于“ *”的使用
“ *”标记表示某个层次上的所有元素。
/authors/author/*:表示在 author 元素(它的父节点为 authors)下的所有子元素(本例为 name和 nationality 两个元素)。 /authors/*/name:表示查找所有名为 name 的元素,而不管它的父节点是谁,或者是 author,也或者是 super-author 元素,但是再上一个父节点确必须是 authors 元素。 //*:表示查找到所有元素。<3>路径分支
方括号表示路径分支。
/authors/author[nationality]/name:表示只查找那些在 authors 元素下包含 nationality 子元素的author 元素的 name 节点。authors/author[nationality=’Russian’]/name:表示查找那些 nationality 子元素值为 German 的 author元素下的 name 节点,而且 author 元素的父节点为 authors。
JSTL包含一系列标准函数,大部分是通用的字符串处理函数。引用JSTL函数库的语法如下:
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>下面通过一个综合实例来演示以上各标签的具体使用方法,创建的 sql_all.jsp 代码如下:
<body bgcolor="#FFFFFF"> <h3>SQL标签库</h3> <hr> <% request.setAttribute("newName", new String("Jake")); //设定newName变量,并保存在request范围内 session.setAttribute("myDbDriver","com.mysql.jdbc.Driver");//设数据库连接驱动到session范围的myDbDriver变量中 session.setAttribute("myDbUrl","jdbc:mysql://localhost/ceshi");//设定数据库连接到session范围的myDbUrl变量中 session.setAttribute("myDbUserName","root");//设定数据库用户名 session.setAttribute("myDbPassword","root");//设定数据库用户密码 %> <%-- 首先设定数据库连接 --%> <sql:setDataSource var="example" driver="${sessionScope.myDbDriver}" url="${sessionScope.myDbUrl}" user="${sessionScope.myDbUserName}" password="${sessionScope.myDbPassword}" /> <%-- 把数据库查询和更新操作放在一个事务中 --%> <sql:transaction dataSource="${example}"> <%-- 使用<sql:update>标签创建一个数据库表mytable --%> <sql:update var="newTable"> create table mytable ( nameid int primary key, name varchar(80) ) </sql:update> <%-- 向mytable表中插入数据 --%> <sql:update var="updateCount"> INSERT INTO mytable VALUES (1,'Tom') </sql:update> <%-- 向mytable表中插入数据,并使用<sql:param>标签插入参数值 --%> <sql:update var="updateCount"> INSERT INTO mytable VALUES (?,'Johnson') <sql:param value="2"/> </sql:update> <%-- 向mytable表中插入数据 --%> <sql:update var="updateCount"> INSERT INTO mytable VALUES (?,?) <sql:param value="3"/> <sql:param value="${newName}"/> </sql:update> <%-- 查询数据库表mytable中所有内容 --%> <sql:query var="deejay"> SELECT * FROM mytable </sql:query> </sql:transaction> <%-- 对返回的Result结果中的每行的列进行迭代处理 ,取出每一列--%> <table border="1"> <c:forEach var="row" items="${deejay.rowsByIndex}"> <tr> <c:forEach var="column" items="${row}"> <td><c:out value="${column}"/></td> </c:forEach> </tr> </c:forEach> </table> <%-- 没有指定每行的列索引,注意与上面的不同, 这里可以指定取出哪一列--%> <table border="1"> <c:forEach var="row" items="${deejay.rows}"> <tr> <td><c:out value="${row.nameid}"/></td> <td><c:out value="${row.name}"/></td> </tr> </c:forEach> </table> <%-- 把mytable数据库表删除 --%> <sql:update var="newTable" dataSource="${example}"> drop table mytable </sql:update> </body>程序说明:
首先进行了数据库连接的各参数的设定,并把它们存储在 session 范围内的变量中,这样有利于在整个 Web 应用中的其他页面中进行调用。把整个的数据库表的创建、插入以及查询操作放置在<sql:transaction>标签设定的一个事务中。在获取查询信息时,本实例使用了两种方法,前一种方法使用索引迭代取出行中每个列的数据;第一种方法没有使用索引,而是通过指定行中的特定列来取得数据。参考资料:
《JSP宝典》