前言
为了降低JSP页面的复杂度,增强代码的重用性,Sun公司制定了一套标准标签库JSTL
一、什么是JSTL
从JSP1.1规范开始,JSP就支持使用自定义标签,使用自定义标签大大降低了JSP页面的复杂度,同时增强了代码的重用性。为此,许多Web应用厂商都定制了自身应用的标签库,然而同一功能的标签由不同的Web应用厂商制定可能是不同的,这就导致市面上出现了很多功能相同的标签,令网页制作者无从选择,为了解决这个问题,Sun公司制定了一套标准标签库(JavaServer Pages Standard Tag Library),简称JSTL。 JSTL虽然被称为标准标签库,而实际上这个标签库是由5个不同功能的标签库共同组成的。在JSTL1.1规范中,为这5个标签库分别指定了不同的URI以及建议使用的前缀,如下表所示。
Core是一个核心标签库,它包含了实现Web应用中通用操作的标签。例如,用于输出文本内容的<c:out>标签、用于条件判断的<c:if>标签、用于迭代循环的<c:forEach>标签。
I18N是一个国际化/格式化标签库,它包含实现Web应用程序的国际化标签和格式化标签。例如,设置JSP页面的本地信息、设置JSP页面的时区、使日期按照本地格式显示等。
SQL是一个数据库标签库,它包含了用于访问数据库和对数据库中的数据进行操作的标签。例如,从数据库中获得数据库连接、从数据库表中检索数据等。由于在软件分层开发模型中,JSP页面仅作为表示层,一般不会在JSP页面中直接操作数据库,因此,JSTL中提供的这套标签库不经常使用。
XML是一个操作XML文档的标签库,它包含对XML文档中的数据进行操作的标签。例如,解析XML文件、输出XML文档中的内容,以及迭代处理XML文档中的元素。XML广泛应用于Web开发,使用XML标签库处理XML文档更加简单方便。
Functions是一个函数标签库,它提供了一套自定义EL函数,包含了JSP网页制作者经常要用到的字符串操作。例如,提取字符串中的子字符串、获取字符串的长度等。
二、JSTL的安装和测试
1.下载JSTL包
从Apache的网站下载JSTL的JAR包。进入“http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/”网址下载JSTL的安装包jakarta-taglibs-standard-1.1.2.zip,然后将下载好的JSTL安装包进行解压,此时,在lib目录下可以看到两个JAR文件,分别为jstl.jar和standard.jar。其中,jstl.jar文件包含JSTL规范中定义的接口和相关类,standard.jar文件包含用于实现JSTL的.class文件以及JSTL中5个标签库描述符文件(TLD)。
2.安装JSTL
将jstl.jar和standard.jar这两个文件复制到chapter07项目的lib目录下,如图所示。
从上图可以看出,jstl.jar和standard.jar这 两个文件已经被导入到chapter07项目的 lib文件夹中,这个过程就相当于在 chapter07项目中安装JSTL,安装完JSTL 后,就可以在JSP文件中使用JSTL标签库。
3.测试JSTL
JSTL安装完成后,就需要测试JSTL安装是否成功。由于在测试的时候使用的是<c:out>标签,因此,需要使用taglib指令导入Core标签库,具体代码如下
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
在上述代码中,taglib指令的uri属性用于指定引入标签库描述符文件的URI,prefix属性用于指定引入标签库描述符文件的前缀,在JSP文件中使用这个标签库中的某个标签时,都需要使用这个前缀。
案例:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head></head>
<body>
<c:out value="Hello World!"></c:out>
</body>
</html>
三、JSTL中的Core标签库
1.<c:out>标签
在JSP页面中,最常见的操作就是向页面输出一段文本信息,为此,Core标签库提供了一个<c:out>标签,该标签可以将一段文本内容或表达式的结果输出到客户端。如果<c:out>标签输出的文本内容中包含需要进行转义的特殊字符,例如>、<、&、'、" 等,<c:out>标签会默认对它们进行HTML编码转换后再输出。<c:out>标签有两种语法格式,具体如下:
语法1:没有标签体的情况
<c:out value="value" [default="defaultValue"] [escapeXml="{true|false}"] />
语法2:有标签体的情况
<c:out value="value" [escapeXml="{true|false}"]> defaultValue </c:out>
value属性用于指定输出的文本内容;
default属性用于指定当value属性为null时所输出的默认值,该属性是可选的(方括号中的属性都是可选的);
escapeXml属性用于指定是否将>、<、&、'、" 等特殊字符进行HTML编码转换后再进行输出,默认值为true。
需要注意的是,只有当value属性值为null时,<c:out>标签才会输出默认值,如果没有指定默认值,则默认输出空字符串。
(1)使用<c:out>标签输出默认值
有两种方式,一是通过使用<c:out>标签的default属性输出默认值,二是通过使用<c:out>标签的标签体输出默认值。
案例:c_out1.jsp
<%@ page language="java" contentType="text/html;charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head></head>
<body>
<%--第1个out标签 --%>
userName属性的值为:
<c:out value="${param.username}" default="unknown" />
<br />
<%--第2个out标签 --%>
userName属性的值为:
<c:out value="${param.username}">
unknown
</c:out>
</body>
</html>
http://localhost:8080/chapter07/c_out1.jsp
http://localhost:8080/chapter07/c_out1.jsp?username=itcast
(2)使用<c:out>标签的escapeXml属性对特殊字符进行转义
<c:out>标签有一个重要的属性escapeXml,该属性可以将特殊的字符进行HTML编码转换后再输出。
案例:c_out2.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head></head>
<body>
<c:out value="${param.username }" escapeXml="true">
<meta http-equiv="refresh" content="0;url=http://www.itcast.cn" />
</c:out>
</body>
</html>
http://localhost:8080/chapter07/c_out2.jsp
源代码
<html>
<head></head>
<body>
<meta http-equiv="refresh" content="0;url=http://www.itcast.cn" />
</body>
</html>
说明escapeXml="true"时,会对特殊字符进行html编码转换,最终以字符串的形式输出。
修改为false时,
<html>
<head></head>
<body>
<meta http-equiv="refresh" content="100;url=http://www.itcast.cn" />
</body>
</html>
没有进行html编码转换,100秒后跳转到“http://www.itcast.cn”。
2.<c:if>标签
在程序开发中,经常需要使用if语句进行条件判断,如果要在JSP页面中进行条件判断,就需要使用Core标签库提供的<c:if>标签,该标签专门用于完成JSP页面中的条件判断,它有两种语法格式,具体如下:
语法1:没有标签体的情况
<c:if test="条件" var="变量名" [scope="{page|request|session|application}"] />
语法2:有标签体的情况,在标签体中指定要输出的内容
<c:if test="条件" var="变量名" [scope="{page|request|session|application}"] >
body content
</c:if>
test属性用于设置逻辑表达式;
var属性用于指定逻辑表达式中变量的名字;
scope属性用于指定var变量的作用范围,默认值为page。如果属性test的计算结果为true,那么标签体将被执行,否则标签体不会被执行。
案例:c_if.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head></head>
<body>
<c:set value="1" var="visitCount" property="visitCount" />
<c:if test="${visitCount==1 }">
This is you first visit. Welcome to the site!
</c:if>
</body>
</html>
3.<c:choose>标签
在程序开发中不仅需要使用if条件语句,还经常会使用if-else语句,为了在JSP页面中也可以完成同样的功能,Core标签库提供了<c:choose>标签,该标签用于指定多个条件选择的组合边界,它必须与<c:when>、<c:otherwise>标签一起使用。 <c:choose>标签没有属性,在它的标签体中只能嵌套一个或多个<c:when>标签和零个或一个<c:otherwise>标签,并且同一个<c:choose>标签中所有的<c:when>子标签必须出现在<c:otherwise>子标签之前,其语法格式如下:
<c:choose>
<!--一个或多个when-->
<c:when test="条件">
内容
</c:when>
<!--零个或一个otherwise-->
<c:otherwise>
内容
</c:otherwise>
</c:choose>
案例:c_choose.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head></head>
<body>
<c:choose>
<c:when test="${empty param.username}">
unKnown user.
</c:when>
<c:when test="${param.username=='itcast'}">
${ param.username} is manager.
</c:when>
<c:otherwise>
${ param.username} is employee.
</c:otherwise>
</c:choose>
</body>
</html>
4.<c:forEach>标签
在JSP页面中,经常需要对集合对象进行循环迭代操作,为此,Core标签库提供了一个<c:forEach>标签,该标签专门用于迭代集合对象中的元素,如Set、List、Map、数组等,并且能重复执行标签体中的内容,它有两种语法格式,具体如下:
语法1:迭代包含多个对象的集合
<c:forEach [var="变量名"] items="集合对象" [varStatus="varStatusName"]
[begin="开始索引"] [end="结束索引"] [step="步长"]>
标签体内容
</c:forEach>
语法2:迭代指定范围内的集合
<c:forEach [var="变量名"] items="集合对象" [varStatus="varStatusName"]
begin="开始索引" end="结束索引" [step="步长"]>
标签体内容
</c:forEach>
var属性用于指将当前迭代到的元素保存到page域中的名称;
items属性用于指定将要迭代的集合对象;
varStatus用于指定当前迭代状态信息的对象保存到page域中的名称;
begin属性用于指定从集合中第几个元素开始进行迭代,begin的索引值从0开始,如果没有指定items属性,就从begin指定的值开始迭代,直到迭代结束为止;
step属性用于指定迭代的步长,即迭代因子的增量。
案例:
c_foreach1.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head></head>
<body>
<%
String[] fruits = { "apple", "orange", "grape", "banana" };
%>
String数组中的元素:
<br />
<c:forEach var="name" items="<%=fruits%>">
${name}<br />
</c:forEach>
<%
Map userMap = new HashMap();
userMap.put("Tom", "123");
userMap.put("Make", "123");
userMap.put("Lina", "123");
%>
<hr/>
HashMap集合中的元素:
<br />
<c:forEach var="entry" items="<%=userMap%>">
${entry.key} ${entry.value}<br />
</c:forEach>
</body>
</html>
c_foreach2.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head></head>
<body>
colorsList集合(指定迭代范围和步长)<br />
<%
List colorsList=new ArrayList();
colorsList.add("red");
colorsList.add("yellow");
colorsList.add("blue");
colorsList.add("green");
colorsList.add("black");
%>
<c:forEach var="color" items="<%=colorsList%>" begin="1"
end="3" step="2">
${color}
</c:forEach>
</body>
</html>
<c:forEach>标签的varStatus属性用于设置一个javax.servlet.jsp.jstl.core.LoopTagStatus类型的变量,这个变量包含了从集合中取出元素的状态信息。使用<c:forEach>标签的varStatus属性可以获取以下信息:
count:表示元素在集合中的序号,从1开始计数;
index:表示当前元素在集合中的索引,从0开始计数;
first:表示当前是否为集合中的第一个元素;
last:表示当前是否为集合中的最后一个元素;
案例:c_foreach3.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head></head>
<body style="text-align: center;">
<%
List userList = new ArrayList();
userList.add("Tom");
userList.add("Make");
userList.add("Lina");
%>
<table border="1">
<tr>
<td>序号</td>
<td>索引</td>
<td>是否为第一个元素</td>
<td>是否为最后一个元素</td>
<td>元素的值</td>
</tr>
<c:forEach var="name" items="<%=userList%>" varStatus="status">
<tr>
<td>${status.count}</td>
<td>${status.index}</td>
<td>${status.first}</td>
<td>${status.last}</td>
<td>${name}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
5.<c:param>标签和<c:url>标签
在开发一个Web应用程序时,通常会在JSP页面中完成URL的重写以及重定向等特殊功能,为了完成这些功能,在Core标签库中,也提供了相应功能的标签,这些标签包括<c:param>、<c:redirect>和<c:url>。其中<c:param>标签用于获取URL地址中的附加参数,<c:url>标签用于按特定的规则重新构造URL,<c:redirect>标签负责重定向。
<c:param>标签用于在URL地址中附加参数,它通常嵌套在<c:url>标签内使用。
<c:param>标签有两种语法格式,具体如下:
语法1:使用value属性指定参数的值
<c:param name="参数名" value="参数值" />
语法2:在标签体中指定参数的值
<c:param name="参数名" value=">
参数值
</c:param>
name属性用于指定参数的名称;
value属性用于指定参数的值,当使用<c:param>标签为一个URL地址附加参数时,它会自动对参数值进行URL编码,例如,如果传递的参数值为“中国”,则将其转换为%e4%b8%ad%e5%9b%bd”后再附加到URL地址后面,这也是使用<c:param>标签的最大好处。
在访问一个JSP页面时,通常会在URL中传递一些参数信息,为了方便完成这种功能,Core标签库中提供了一个<c:url>标签,该标签可以在JSP页面中构造一个新的地址,实现URL的重写。<c:url>标签有两语法格式,具体如下:
语法1:没有标签实体的情况
语法2:有标签实体的情况,在标签体中指定构造URL参数
value属性用于指定构造的URL;
context属性用于指定导入同一个服务器下其他Web应用的名称;
var属性用于指定将构造的URL地址保存到域对象的属性名称;
scope属性用于指定将构造好的URL保存到域对象中。
案例:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head></head>
<body>
使用绝对路径构造URL:<br />
<c:url var="myURL"
value="http://localhost:8080/chapter07/register.jsp">
<c:param name="username" value="张三" />
<c:param name="country" value="中国" />
</c:url>
<a href="${myURL}">register.jsp</a><br />
使用相对路径构造URL:<br />
<c:url var="myURL"
value="register.jsp?username=Tom&country=France" />
<a href="${ myURL}">register.jsp</a>
</body>
</html>
结果:
<html>
<head></head>
<body>
使用绝对路径构造URL:<br />
<a href="http://localhost:8080/chapter07/register.jsp?username=%e5%bc%a0%e4%b8%89&country=%e4%b8%ad%e5%9b%bd">
register.jsp
</a><br />
使用相对路径构造URL:<br />
<a href="register.jsp?username=Tom&country=France">register.jsp</a>
</body>
</html>