第3章Tag文件与Tag标记 本章导读 主要内容 Tag文件的结构 Tag标记 Tag文件中的常用指令 难点 Tag文件中的attribute指令 Tag文件中的variable指令 关键实践 解析单词 一个Web应用中的许多JSP页面可能需要使用某些相同的信息,如都需要使用相同的导航栏、标题等。如果能将许多页面都需要的共同的信息形成一种特殊文件,而且各个JSP页面都可以使用这种特殊的文件,那么这样的特殊文件就是可复用的代码。代码复用是软件设计的一个重要方面、是衡量软件可维护性的重要指标之一。 第2章学习了include指令标记和include动作标记,使用这两个标记可以实现代码的复用。但是,在某些情况下,使用include指令标记和include动作标记有一定的缺点,比如,如果include指令标记或动作标记要处理的文件是一个JSP文件,那么用户可以在浏览器的地址栏中直接输入该JSP文件所在Web服务目录访问这个JSP文件,这可能不是Web应用所希望发生的,因为该JSP文件也许仅仅是个导航条,仅仅供其他JSP文件使用include指令标记或动作标记来嵌入或动态加载的,而不是让用户直接访问的。另外,include指令标记和include动作标记允许所要处理的文件存放在Web服务目录中的任意子目录中,不仅显得杂乱无章,而且使得include标记和所处理文件的所在目录的结构形成了耦合,不利于Web应用的维护。 本章我们将学习一种特殊的文本文件: Tag文件。Tag文件和JSP文件很类似,可以被JSP页面动态加载调用,实现代码的复用(但用户不能通过该Tag文件所在Web服务目录直接访问Tag文件)。 本章在webapps目录下新建一个Web服务目录ch3,除非特别约定,例子中的JSP页面均保存在ch3目录中。 视频讲解 3.1Tag文件 3.1.1Tag文件的结构 Tag文件是扩展名为.tag的文本文件,其结构和JSP文件类似。一个Tag文件中可以有普通的HTML标记符、某些特殊的指令标记(见3.4节)、成员变量声明和方法的定义、Java程序片和Java表达式。以下是一个简单的Tag文件oddNumberSum.tag,负责计算100内的全部奇数的代数和。 oddNumberSum.tag <%@ tag pageEncoding="utf-8"%>
1~100内的奇数之和: <%int sum=0,i=1; for(i=1;i<=100;i++){ if(i%2==1) sum=sum+i; } out.println(sum); %>
3.1.2Tag文件的保存 Tag文件所在目录 Tag文件可以实现代码的复用,即Tag文件可以被许多JSP页面使用。为了能让一个Web应用中的JSP页面使用某一个Tag文件,必须把这个Tag文件存放到Tomcat服务器指定的目录中,也就是说,如果某个Web服务目录下的JSP页面准备调用一个Tag文件,那么必须在该Web服务目录下,建立如下的目录结构: Web服务目录\WEB-INF\tags 例如: ch3\WEB-INF\tags 其中的WEBINF(字母大写)和tags都是固定的目录名称,而tags下的子目录的名称可由用户给定。 一个Tag文件必须保存到tags目录或其下的子目录中。这里把3.1.1节中的oddNumberSum.tag保存到 ch3\WEBINF\tags 目录中。 Tag文件的编码 保存Tag文件时按照Tag文件指定的编码保存,例如Tag文件使用tag指令(见稍后的3.4节): <%@ tag pageEncoding="utf-8"%> 指定的编码是UTF8,因此需要按照UTF8编码保存Tag文件。例如,用文本编辑器“记事本”编辑Tag文件,在保存该Tag文件时,将“保存类型(T)”选择为“所有文件(*.*)”,将“编码(E)”选择为“UTF8”。 3.2Tag标记 3.2.1Tag标记与Tag文件 视频讲解 某个Web服务目录下的Tag文件只能由该Web服务目录中的JSP页面调用,JSP页面必须通过Tag标记来调用一个Tag文件。 Tag标记的名字和Tag文件的名字一致,也就是说,当我们编写了一个Tag文件并保存到特定目录中后(见3.1.2节),也就给出了一个Tag标记,该标记的格式为:
<%--使用Tag标记: --%>
排序数据
菜单:
购物小票:
<%= str %>
"+ite.next());
}
%>
图3.3调用Tag文件排序数据
3.3.4variable指令
Tag文件通过使用attribute指令,可以使得调用该Tag文件的JSP页面动态地向其传递数据。在某些Web应用中,JSP页面不仅希望向Tag文件传递数据,而且希望Tag文件能返回数据给JSP页面。比如,许多JSP页面可能都需要调用某个Tag文件对某些数据进行基本的处理,但不希望Tag文件做进一步的特殊处理以及显示数据,因为各个JSP页面对数据的进一步处理或显示格式的要求是不同的。因此,JSP页面希望Tag文件将数据的基本处理结果存放在某些对象中,将这些对象返回给当前JSP页面即可。
Tag文件通过使用variable指令可以将Tag文件中的对象返回给调用该Tag文件的JSP页面。
variable指令的格式
variable指令的格式如下:
<%@ variable name-given="对象名" variable-class="对象类型" scope="有效范围"%>
variable指令中属性namegiven的值就是Tag文件返回给JSP页面的对象。该对象的名字必须符合标识符规定,即名字可以由字母、下画线、美元符号和数字组成,并且第一个字符不能是数字字符。variable指令中属性variableclass的值是返回的对象的类型,对象的类型必须带有包名,比如java.lang.Double、java.time. LocalDate等类型。如果variable指令中没有使用variableclass给出对象的类型,那么对象的类型是java.lang.String类型。
variable指令中scope属性的值指定对象的有效范围,scope的值可以取AT_BEGIN、NESTED和AT_END。当scope的值是AT_BEGIN时,JSP页面一旦开始使用Tag标记,就得到了variable指令返回给JSP页面的对象,JSP页面就可以在Tag标记的标记体中或Tag标记结束后的各个部分中使用variable指令返回给JSP页面的对象。当scope的值是NESTED时,JSP页面只可以在Tag标记的标记体中使用variable指令返回给JSP页面的对象。当scope的值是AT_END时,JSP页面只可以在Tag标记结束后。才可以使用variable指令返回给JSP页面的对象。
下面的variable指令给出的对象的名字是time,类型为java.time.LocalDate,有效范围是AT_END:
<%@ variable name-given="time"
variable-class="java.time.LocalDate" scope="AT_END"%>
对象的返回
Tag文件为了给JSP页面返回一个对象,就必须将返回的对象的名字以及该对象的引用存储到Tomcat服务器提供的内置对象jspContext中。Tag文件只有将对象的名字及其引用存储到jspContext中,JSP页面才可以使用该对象。比如,Tag文件的variable指令:
<%@ variable name-given="time"
variable-class="java.time.LocalDate" scope="AT_END"%>
为JSP页面返回名字是time的LocalDate对象。那么Tag文件中必须让jspContext调用
setAttribute("对象名",对象的引用);
方法存储名字是time的对象以及该对象的引用,例如:
jspContext.setAttribute("time",LocalDate .now());
将名字是time的LocalDate对象存储到jspContext中。
下面的例3_4中,JSP页面example3_4.jsp将String对象交给Tag文件handleData.tag,handleData.tag解析出String对象的字符序列中的全部数字,并计算出数字总和,将数字总和放在Double对象price中,然后返回给JSP页面example3_4.jsp。example3_4.jsp输出price对象中的数字总和。handleData.tag.tag存放在ch3\WEBINF\tags\example4目录中,example3_4.jsp保存在ch3目录中。
例3_4
example3_4.jsp(效果如图3.4所示)
<%@ page contentType="text/html"%>
<%@ page pageEncoding="utf-8"%>
<%@ taglib tagdir="/WEB-INF/tags/example4" prefix="getPrice"%>
<% String str="麻辣豆腐:20.6元,红烧肉:68.9元,烤鸭:199元";
%>
"<%= str %>"
价格总和:
<%= price %><%--使用Tag标记返回的Double对象price --%>
"<%= str %>"
价格总和:
<%= price %>
<%
Iterator
");
while(ite.hasNext()) {//遍历集合
out.print(" "+ite.next());
}
%>
<%=year %>年<%=month %>月的日历:
习 题 3
1. 用户可以使用浏览器直接访问一个Tag文件吗?
2. Tag文件应当存放在怎样的目录中?
3. Tag文件中的tag指令可以设置哪些属性的值?
4. Tag文件中的attribute指令有怎样的作用?
5. Tag文件中的variable指令有怎样的作用?
6. 编写两个Tag文件Rect.tag和Circle.tag。Rect.tag负责计算并显示矩形的面积,Circle.tag负责计算并显示圆的面积。编写一个JSP页面lianxi6.jsp,该JSP页面使用Tag标记调用Rect.tag和Circle.tag。调用Rect.tag时,向其传递矩形的两个边的长度; 调用Circle.tag时,向其传递圆的半径。
7. 编写一个Tag文件: GetArea.tag负责求出三角形的面积,并使用variable指令返回三角形的面积给调用该Tag文件的JSP页面。JSP页面负责显示Tag文件返回的三角形的面积。JSP在调用Tag文件时,使用attribute指令将三角形三边的长度传递给Tag文件。one.jsp和two.jsp都使用Tag标记调用GetArea.tag。one.jsp返回的三角形的面积保留最多3位小数,two.jsp返回的三角形的面积保留最多6位小数。
<%
int n=0;
while(n星期日 星期一 星期二 星期三
星期四 星期五 星期六