1. JSTL标签库概述
1.1. 什么是JSTL标签库
JSTL全称为JSP Standard Tag Library,即JSP标准标签库。JSTL最初是一套Java官方的标签库解决方案,自从JavaEE 5之后被定义为标准的标签库。JSTL规范由Sun公司定制,Apache的Jakarta小组负责实现,目前的版本是JSTL1.2。
EL最初定义在JSTL1.0规范中,在JSP2.0之后,EL已经正式成为JSP规范的一部分。在JSTL1.1规范中,已经没有了EL的内容,不过在JSTL中仍然可以使用EL。
JSTL的目标是为了简化JSP页面的设计,JSTL的使用为页面设计人员和程序开发人员的分工协作提供了便利。
JSTL虽然叫做标准标签库,但实际上是由五个不同功能的标签库组成的。分别为core标签库、fmt标签库、SQL标签库、XML标签库及Functions标签库,其中Functions标签库就是前面提到了EL表达式的函数库,下面主要学习core标签库和fmt标签库。
1.2. 百度百科
JSTL(JSP Standard Tag Library,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,是由apache的jakarta小组来维护的。JSTL只能运行在支持JSP1.2和Servlet2.3规范的容器上,如tomcat 4.x。在JSP 2.0中也是作为标准支持的。
JSTL 1.0 发布于 2002 年 6 月,由四个定制标记库(core、format、xml 和 sql)和一对通用标记库验证器(ScriptFreeTLV 和 PermittedTaglibsTLV)组成。core 标记库提供了定制操作,通过限制了作用域的变量管理数据,以及执行页面内容的迭代和条件操作。它还提供了用来生成和操作 URL 的标记。顾名思义,format 标记库定义了用来格式化数据(尤其是数字和日期)的操作。它还支持使用本地化资源束进行 JSP 页面的国际化。xml 库包含一些标记,这些标记用来操作通过 XML 表示的数据,而 sql 库定义了用来查询关系数据库的操作。
如果要使用JSTL,则必须将jstl.jar和 standard.jar文件放到classpath中,如果你还需要使用XML processing及Database access (SQL)标签,还要将相关JAR文件放到classpath中,这些JAR文件全部存在于下载回来的zip文件中。
1.3. 维基百科
JSP标准标签库(JSP Standard Tag Library)是Java EE网络应用程序开发平台的组成部分。它在JSP规范的基础上,扩充了一个JSP的标签库来完成一些通用任务,比如XML数据处理、条件执行、数据库访问、循环和国际化。
JSTL是在JCP下,作为JSR 52被开发出来的。2006年5月8日发布了JSTL 1.2,接下来是2011年12月7日的JSTL 1.2.1。
JSTL提供了一个有效的途径,以在JSP页面中嵌入逻辑,而不是直接嵌入Java代码。使用标准标签集,减少了Java代码导致的不连续,从而提高代码的可维护性,并达到应用软件代码开发与用户界面间的关注点分离。
2. JSTL的core标签库
2.1. <c:out>标签
<c:out>标签用于计算一个表达式并将结果输出到当前的JspWriter对象。<c:out>标签的功能类似于JSP的表达式<%=expression%>。
<c:out>标签的语法格式如下:
<c:out value="表达式" escapeXml="是否转义" default="默认值"></c:out>
- value属性:指定被计算的表达式。
- escapeXml属性:确定在结果字符中的字符“<”、“>”、“’”、“””和“&”是否应该被转换为对应的字符引用或预定义实体引用,默认值为true。
如果值为true,那么字符“<”、“>”、“’”、“””和“&”将按照如下表进行转换。
字符 |
字符实体代码 |
< |
< |
> |
> |
> ‘ |
' |
“ |
" |
& |
& |
- default属性:如果value为null,那么将使用这个默认值。
下面是<c:out>标签的具体用法:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title> out.jsp </title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <% pageContext.setAttribute("name", "longestory"); %> <c:out value="${name}"></c:out><br/> <c:out value="<script>alert('hello longestory.');</script>" escapeXml="false"></c:out><br/> <c:out value="${helloworld}" default="unknown"></c:out> </body> </html>
2.2. <c:set>标签
<c:set>标签用于设置范围变量的值或者JavaBean对象的属性。
<c:set>标签的语法格式如下:
<c:set var="变量名称" value="表达式" scope="JSP域范围"></c:set>
- var属性:将value属性计算表达式得到的结果,保存在该变量名称中。
- value属性:指定被计算的表达式。
- scope属性:var属性指定的变量所使用的范围(JSP域范围)。
- target属性:要设置属性的对象。必须是JavaBean对象(对应的属性有setter方法)或者java.util.Map对象。
- property属性:要设置的target对象的属性名称。
下面是<c:set>标签的具体用法:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>set.jsp</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <c:set var="name" value="longestory" scope="session"></c:set> <c:out value="name"></c:out> <br> <jsp:useBean id="user" class="app.java.bean.User" scope="session" /> <c:set target="${user }" property="age" value="18"></c:set> <c:out value="${user.age }"></c:out> </body> </html>
2.3. <c:remove>标签
<c:remove>标签用于移除指定范围的变量。
<c:remove>标签的语法格式如下:
<c:remove var="变量名称" scope="JSP域范围"/>
- var属性:要移除指定范围的变量名称。
- scope属性:var属性指定的变量的范围(JSP域),默认是page。
下面是<c:remove>标签的具体用法:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>remove.jsp</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <% pageContext.setAttribute("a", "pageContext"); request.setAttribute("a", "session"); session.setAttribute("a", "session"); application.setAttribute("a", "application"); %> <!-- 删除所有域中的name为a的数据 --> <c:remove var="a"/> <c:out value="${a }" default="none"/> </body> </html>
2.4. <c:if>标签
<c:if>标签用于实现Java语言中的if语句的功能。
<c:if>标签的语法格式如下:
<c:if test="条件" var="变量名称" scope="JSP域范围"></c:if>
- test属性:测试的条件,用于判断标签体是否应该被执行。
- var属性:将测试条件的结果值保存在该变量中,该变量的值类型为Boolean。
- scope属性:var属性指定变量的JSP域范围,默认值为page。
下面是<c:if>标签的具体用法:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>if.jsp</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <c:set var="name" value="longestory"/> <c:if test="${not empty name }" var="test" scope="session"> <c:out value="${name }"/> </c:if> <br> <c:if test="${test }"> <c:out value="helloworld"></c:out> </c:if> </body> </html>
2.5. <c:choose>标签
<c:choose>标签、<c:when>标签和<c:otherwise>标签一起实现互斥条件的执行,类似于Java语言的if/else if/else语句。
<c:choose>标签、<c:when>标签和<c:otherwise>标签的语法格式如下:
<c:choose> <c:when test="条件"></c:when> <c:otherwise></c:otherwise> </c:choose>
下面是<c:choose>标签、<c:when>标签和<c:otherwise>标签的具体用法:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>choose.jsp</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <c:set var="c" value="${param.score }"/> <c:choose> <c:when test="${c > 100 || c < 0 }">输入有误,请输入正确的成绩:0~100之间。</c:when> <c:when test="${c >= 90 }">A</c:when> <c:when test="${c >= 80 }">B</c:when> <c:when test="${c >= 70 }">C</c:when> <c:when test="${c >= 60 }">D</c:when> <c:otherwise>E</c:otherwise> </c:choose> </body> </html>
2.6. <c:url>标签
<c:url>标签使用正确的URL重写规则构造一个URL。
<c:url>标签的语法格式如下:
<c:url value="url路径" var="变量名称" scope="JSP域范围"></c:url>
- value属性:要处理的URL。
- var属性:将处理的URL保存在该变量中,该变量的类型为String。
- scope属性:var属性指定变量的JSP域范围,默认值为page。
下面是<c:url>标签的具体用法:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>url.jsp</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <a href="<c:url value='/servlet/AServlet'/>">链接1</a><br/> <c:url value="/servlet/AServlet" var="url" scope="request"> <c:param name="username" value="longestory" /> <c:param name="password" value="123" /> </c:url> <a href="${requestScope.url }">链接2</a> </body> </html>
2.7. <c:forEach>标签
<c:forEach>标签用于对包含了多个对象的集合进行迭代,重复执行它的标签体,或者重复迭代固定的次数。
<c:forEach>标签的语法格式如下:
<c:forEach var="变量名称" begin="起始位置" end="截至位置" step="步长" items="集合对象" varStatus="迭代状态"></c:forEach>
- var属性:用于迭代的变量名称。
- begin属性:指定迭代的起始位置。
- end属性:指定迭代的截至位置。
- step属性:迭代的步长,默认的步长是1。
- items属性:要迭代的集合对象。
- varStatus属性:要迭代的状态,可以获取迭代过程中的一些状态。
对于<c:forEach>标签的实际用法,大体分为两种:
- 循环变量,指定开始和结束位置(计数):
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>foreach.jsp</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <c:forEach var="i" begin="1" end="10"> ${i }<br/> </c:forEach> <br/> <c:set var="sum" value="0"/> <c:forEach var="i" begin="1" end="100"> <c:set var="sum" value="${sum + i }"/> </c:forEach> sum = ${sum } </body> </html>
- 循环遍历集合,其中包含数组、List或Map集合等:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>foreach.jsp</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <% String[] arr = {"one", "two", "three"}; pageContext.setAttribute("arr", arr); List<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); pageContext.setAttribute("abc", list); Map<String,String> person = new LinkedHashMap<String,String>(); person.put("name", "zhangSan"); person.put("age", "23"); person.put("sex", "male"); pageContext.setAttribute("p", person); %> <c:forEach items="${arr }" var="str"> ${str }<br/> </c:forEach> <br/> <c:forEach items="${abc }" var="str"> ${str }<br/> </c:forEach> <br/> <c:forEach items="${p }" var="entry"> ${entry.key } = ${entry.value }<br/> </c:forEach> </body> </html>
- 在迭代中通过varStatus属性获取迭代中的状态。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>foreach.jsp</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <c:forEach items="${arr }" var="str" varStatus="vs"> first: ${vs.first }, last: ${vs.last }, count: ${vs.count }, index: ${vs.index }, current: ${vs.current }<br/> </c:forEach> </body> </html>
3. 自定义标签
3.1. 为什么要自定义
JSP中设计自定义标签的目的就是为了实现HTML代码重用。自定义标签可以实现非常复杂的功能,但使用起来很简单。
在JavaEE规范中,是不建议在JSP页面直接编写Java代码的,而是通过自定义标签来调用对应的Java代码实现某些功能。因为企业的业务需求是多种多样的,常见的开源框架只能提供通用的Java代码功能。如果要实现既定业务逻辑功能,就可以通过自定义标签方式解决。
3.2. 自定义标签步骤
在JavaEE的API中提供了Tag接口,我们可以通过实现该接口,完成自定义标签的功能。Tag接口在API中提供了如下几种方法,实现该接口时需要重写这几种方法:
Method Summary |
|
int |
doEndTag() |
int |
doStartTag() |