目录
如果说出现了如下的报错信息:java.lang.NoClassDefFoundError:javax/servlet/jsp/tagext/TagLibraryValidator
实验七 JSTL与标签文件
一、实验目的
1. 了解什么是JSTL?
2. 掌握JSTL的核心库标签的使用。
3. 掌握标签文件的开发和使用。
二、实验原理
JSP标准标签库(JSP Standard Tag Library,简称JSTL)是一个为实现Web应用程序的常用功能而开发的标签库集合。功能包括基本输入输出、流程控制、XML文件解析、数据库查询、国际化和文本格式化等。JSTL主要由下面几个库组成:
- 核心标签库;XML标签库;格式化/国际化标签库;数据库标签库;函数标签库。
这些库都很有用,但我们这里只学习核心库的使用。核心库的标签又可以分成四类,如表12.1所示:
表12.1 按功能分类的核心库的标签
JSTL标签类别 | JSTL标签 | 标签说明 |
通用目的 | <c:out> <c:catch> | 在页面中显示内容 捕获异常 |
变量支持 | <c:set> <c:remove> | 设置一个EL变量值 清除一个EL变量 |
流程控制 | <c:if> <c:choose> <c:forEach> <c:forTokens> | 根据一个属性等于一个值改变处理 根据一个属性等于一组值改变处理 对集合中的每个对象作重复处理 对给定一个文本域中的每个子串执行处理 |
URL处理 | <c:url> <c:import> <c:redirect> | 重写URL并对它们的参数编码 访问web应用程序外部的内容 告诉客户浏览器访问另一个URL |
标签文件(tag file)也是JSP 2.0新增的功能,它的目的是使JSP页面开发人员仅使用JSP语法就能开发标签库而无须编写Java程序。所谓标签文件就是直接使用JSP语法编写的标签。标签文件的扩展名一般为.tag或.tagx,如果标签文件包含其他完整的或片段的标签文件,JSP 2.0建议其扩展名为.tagf。
在JSP页面中使用标签文件,需要在taglib动作中使用tagdir属性指定标签文件所在的目录,例如:
<%@ taglib prefix="mytag" tagdir="/WEB-INF/tags"%>
三、实验内容与步骤
(一)JSTL的安装和测试
【步骤1】要在JSP页面中使用JSTL标签,首先必须安装JSTL库。可以到Jakarta网站下载最新版本的JSTL,网址为http://jakarta.apache.org/,目前最新版本为1.1.2版,它支持JSP 2.0和Servlet 2.4。
如果安装了Tomcat,可以在示例应用程序中获得JSTL,它位于<CATALINA_HOME>\webapps\ examples\WEB-INF\lib目录中,共有两个文件:jstl.jar和standard.jar。将这两个文件复制到你的Web应用程序的WEB-INF\lib目录中,就安装了JSTL。
jstl.jar和standard.jar在哪里下载?
当找不到的情况下,可以从如下链接下载:
百度网盘
链接:https://pan.baidu.com/s/14LfHseLQ4g1n8jRrHtxaVA?pwd=bear
提取码:bear将 jakarta-taglibs-standard/jakarta-taglibs-standard-1.1.2/lib/ 下的两个 jar 文件:standard.jar 和 jstl.jar 文件拷贝到 /WEB-INF/lib/ 下。
如果说出现了如下的报错信息:java.lang.NoClassDefFoundError:javax/servlet/jsp/tagext/TagLibraryValidator
HTTP状态 500 - 内部服务器错误
________________________________________
类型 异常报告
消息 java.lang.NoClassDefFoundError: javax/servlet/jsp/tagext/TagLibraryValidator
描述 服务器遇到一个意外的情况,阻止它完成请求。
例外情况
jakarta.servlet.ServletException: java.lang.NoClassDefFoundError: javax/servlet/jsp/tagext/TagLibraryValidator
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:333)
jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
根本原因。
java.lang.NoClassDefFoundError: javax/servlet/jsp/tagext/TagLibraryValidator
java.base/java.lang.ClassLoader.defineClass1(Native Method)
java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2352)
org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:800)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1317)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1165)
java.base/java.lang.ClassLoader.defineClass1(Native Method)
java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2352)
org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:800)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1317)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1165)
org.apache.jasper.compiler.TagLibraryInfoImpl.createValidator(TagLibraryInfoImpl.java:355)
org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:195)
org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:429)
org.apache.jasper.compiler.Parser.parseDirective(Parser.java:487)
org.apache.jasper.compiler.Parser.parseElements(Parser.java:1444)
org.apache.jasper.compiler.Parser.parse(Parser.java:138)
org.apache.jasper.compiler.ParserController.doParse(ParserController.java:245)
org.apache.jasper.compiler.ParserController.parse(ParserController.java:106)
org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:211)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:396)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:372)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:356)
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:603)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:396)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:380)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:328)
jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
根本原因。
java.lang.ClassNotFoundException: javax.servlet.jsp.tagext.TagLibraryValidator
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1353)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1165)
java.base/java.lang.ClassLoader.defineClass1(Native Method)
java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2352)
org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:800)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1317)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1165)
java.base/java.lang.ClassLoader.defineClass1(Native Method)
java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2352)
org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:800)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1317)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1165)
org.apache.jasper.compiler.TagLibraryInfoImpl.createValidator(TagLibraryInfoImpl.java:355)
org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:195)
org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:429)
org.apache.jasper.compiler.Parser.parseDirective(Parser.java:487)
org.apache.jasper.compiler.Parser.parseElements(Parser.java:1444)
org.apache.jasper.compiler.Parser.parse(Parser.java:138)
org.apache.jasper.compiler.ParserController.doParse(ParserController.java:245)
org.apache.jasper.compiler.ParserController.parse(ParserController.java:106)
org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:211)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:396)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:372)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:356)
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:603)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:396)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:380)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:328)
jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
查看Tomcat的版本,Tomcat10版本需要用:
jakarta.servlet.jsp.jstl-2.0.0.jar
jakarta.servlet.jsp.jstl-api-2.0.0.jar
注:lib下只能有这两个jstl包,不能有其他的jstl包,不然依旧会报错以上两个jar包依然在通过百度网盘下载链接下载的文件中,在jakarta-taglibs-standard/下
【步骤2】一个简单的测试JSP页面jstl_test.jsp
<%@ page contentType="text/html;charset=gb2312" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head><title>Using JSTL</title></head>
<body>
<c:out value="Welcome to using JSTL" />
<br>
Request Method:${pageContext.request.method}<br>
Remote Address:${pageContext.request.remoteAddr}
</body>
</html>
如果页面运行产生下面结果,说明JSTL安装正确,可以使用。
图12.1 jstl_test.jsp 页面的运行结果
说明:使用JSTL我们不用建立标签库描述文件,因为该文件已经包含在standard.jar文件中了,JSP容器可以找到该文件。另外,也可以不用配置web.xml文件,因为JSP容器使用隐含映射的方式可以将标准的URI映射到适当的标签库上。
(二)表达式相关标签的使用
下面的core_expression.jsp演示了<c:out>、<c:set>和<c:remove>标签的使用,代码如下:
<%@ page contentType="text/html;charset=GB2312" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>表达式相关的标签</title>
</head>
<body>
<h2>使用<c:out value="<c:out> <c:set> <c:remove>" />的例子</h2>
<hr>
<c:set scope="page" var="number">
<c:out value="${5}"/>
</c:set>
<br>
<c:set scope="request" var="number">
<c:out value="${15}"/>
</c:set>
<br>
<c:set scope="session" var="number">
<c:out value="${25}"/>
</c:set>
不同作用域的number变量的初始值</p>
pageScope.number =<c:out value="${pageScope.number}" default="No Data" />
<br>
requestScope.number =<c:out value="${requestScope.number}"
default="No Data" />
<br>
sessionScope.number =<c:out value="${sessionScope.number}"
default="No Data" />
<br>
<p><c:out value='执行<c:remove var="number" />之后'/></p>
<c:remove var="number" scope="request" />
pageScope.number =<c:out value="${pageScope.number}"
default="No Data" />
<br>
requestScope.number =<c:out value="${requestScope.number}"
default="No Data" />
<br>
sessionScope.number =<c:out value="${sessionScope.number}"
default="No Data" />
<br>
</body>
</html>
(三)流程控制标签的使用。本实验包括2个页面,一个是flowControl.html,一个是flowControl.jsp。
【步骤1】flowControl.html的代码如下:
<html>
<head>
<title>JSTL中用于流程控制的标签</title>
</head>
<body>
<h2>使用JSTL流程控制标签</h2>
请选择一个填入文本框中:Tom\Jerry\Mike\Ben
<form method="post" action="flowControl.jsp">
<p>姓名:<input type="text" name="username" size="15" /></p>
<p> <input type="submit" value="传送"/>
<input type="reset" value="清除"/></p>
</form>
</body>
</html>
【步骤2】flowControl.jsp的代码如下:
<%@ page contentType="text/html;charset=GB2312" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>JSTL中用于流程控制的标签</title>
</head>
<body>
<h2>标签c:if的使用</h2>
<c:if test="${param.username == 'Tom'}" var="condition" scope="session">
您好,Tom
</c:if>
<c:if test="${param.username == 'Jerry'}" var="condition" scope="session">
您好,Jerry
</c:if>
<c:if test="${param.username == 'Mike'}" var="condition" scope="session">
您好,Mike
</c:if>
<c:if test="${param.username == 'Ben'}" var="condition" scope="session">
您好,Ben
</c:if>
<h2>标签c:choose c:when c:otherwise使用</h2>
<c:choose>
<c:when test="${param.username == 'Tom'}">
您好,Tom
</c:when>
<c:when test="${param.username == 'Jerry'}">
您好,Jerry
</c:when>
<c:when test="${param.username == 'Mike'}">
您好,Mike
</c:when>
<c:otherwise>
您好,Ben
</c:otherwise>
</c:choose>
</body>
</html>
执行flowControl.jsp的结果如下图所示:
图12.2 flowControl.html页面的运行结果
在文本框中输入Tom后,点击“传送”按钮,则出现下面的结果:
图12.3 flowControl.jsp页面的运行结果
HTML网页出现乱码问题:
在header标签中加入:<meta charset="UTF-8">
(四)URL相关标签的使用
【步骤1】included.jsp是被包含的页面,代码如下:
<%@ page contentType="text/html;charset=gb2312" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head><title>Included Page</title></head>
<body>
<h3>这是被包含页面中的内容</h3>
用户名:<c:out value="${param.userName}" />
</body>
</html>
【步骤2】import_test.jsp是包含页面,代码如下:
<%@ page contentType="text/html;charset=gb2312" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head><title>Using URL JSTL</title></head>
<body>
<h3>这是包含页面中的内容</h3>
<c:import url="included.jsp" charEncoding = "gb2312">
<c:param name="userName" value="Harry Porter" />
</c:import>
<br>
</body>
</html>
运行该页面,结果如下图所示:
图12.4 import_test.jsp页面的运行结果
【步骤3】redirect_test.jsp测试了重定向标签的使用,其代码如下:
<%@ page contentType="text/html;charset=gb2312" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head><title>Using Redirect Tag</title></head>
<body>
<h3>使用redirect标签</h3>
<c:redirect url = "import_test.jsp">
<c:param name = "userName" value = "哈里.波特" />
</c:redirect>>
<c:out value="该代码不会被执行" />
</body>
</html>
该页面的执行结果与前面的图一样。
(五)创建简单的标签文件
【步骤1】创建一个名为example.tag的简单的标签文件,代码如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:forTokens items="0 1 1 2 3 5" delims=" " var="fibNum">
<c:out value="${fibNum}"/>
</c:forTokens>
注意:将该文件存放在Web应用程序的WEB-INF/tags目录中。
【步骤2】创建一个名为example.jsp的页面,代码如下:
<%@ taglib prefix="ex" tagdir="/WEB-INF/tags" %>
<html><body>
The first six numbers in the Fibonacci sequence are:
<ex:example/>
</body></html>
执行该JSP页面,结果如下:
图12.5 example.jsp页面的运行结果
(六)使用标签文件指令控制标签
【步骤1】下面的标签文件使用了tag指令的dynamic-attributes属性。dynatt.tag文件的代码如下:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ tag dynamic-attributes="attrib" %>
<c:forEach items="${attrib}" var="att">
${att.value}<br>
</c:forEach>
【步骤2】使用该标签文件的JSP文件dynatt_test.jsp代码如下:
<%@ taglib prefix="dyn" tagdir="/WEB-INF/tags" %>
<html><body>
<dyn:dynatt first="first" second="second" third="third"/>
</body></html>
该JSP页面的运行结果为:
图12.6 dynatt_test.jsp页面的运行结果
四、思考题
1. JSTL的核心库有哪几类标签,各类中有哪些标签?
(1)核心标签(Core Tags):
<c:out>:输出表达式或值。
<c:set>:设置变量的值。
<c:remove>:移除指定的变量。
<c:catch>:捕获异常并处理。
<c:if>:条件判断。
<c:choose>:多分支选择。
<c:forEach>:迭代集合或数组。
(2)格式化标签(Formatting Tags):
<fmt:formatDate>:格式化日期。
<fmt:parseDate>:解析日期。
<fmt:formatNumber>:格式化数字。
<fmt:parseNumber>:解析数字。
<fmt:bundle>:加载资源包。
(3)SQL标签(SQL Tags):
<sql:setDataSource>:设置数据源。
<sql:query>:执行查询操作。
<sql:update>:执行更新操作。
<sql:param>:设置参数。
(4)XML标签(XML Tags):
<x:out>:输出XML内容。
<x:parse>:解析XML文档。
这些标签提供了在JSP页面中进行逻辑控制、数据格式化、数据库操作和XML处理等常见功能的便捷方式。
2.使用标签文件有什么好处?标签文件与JSP 文件的主要区别有哪些?
(1)标签文件(Tag Files)是一种可重用的、自定义的JSP标签,可以帮助简化JSP页面的开发和维护。使用标签文件有以下几个主要好处:
模块化和重用:标签文件允许将特定功能或组件封装为一个标签,以便在多个JSP页面中重复使用,从而提高代码的重用性和可维护性。
降低耦合度:通过将特定功能封装在标签文件中,可以降低JSP页面的复杂度,减少不同部分之间的耦合度,使代码更易于理解和维护。
提高可读性:标签文件可以提高JSP页面的可读性,使页面结构更清晰,易于理解,同时也便于团队协作和代码管理。
(2)标签文件与普通的JSP文件相比,主要区别在于:
语法:标签文件使用.tag作为文件扩展名,而JSP文件使用.jsp扩展名。
用途:标签文件用于定义自定义标签,而JSP文件用于渲染页面内容。
结构:标签文件通常包含标签处理器和标签体,用于定义自定义标签的行为和展示内容,而JSP文件主要包含HTML和Java代码混合的内容,用于生成页面。
总的来说,标签文件的使用可以帮助开发者更好地组织和重用代码,使JSP页面的开发更加模块化和可维护。