JSP标记是JSP页面中很重要的组成部分,JSP标记包括指令标记、动作标记和自定义标记。其中自定义标记主要讲述与Tag文件有关的Tag标记。
一 指令标记page
Page指令标记,简称page指令,用来定义整个JSP页面的一些属性和这些属性的值。可以用一个page指令指定多个属性的值,也可以使用多个page指令分别为每个属性指定值。Page指令的作用对整个页面有效,与其书写的位置无关,习惯把page指令写在整个页面的最前面。Page指令的格式如下:
<%@ page 属性1=”属性1的值” 属性2=”属性2的值” ... %>
Page指令标记可以为下列属性指定值:contentType属性,import属性,language属性,session属性,buffer属性,autoFlush属性,isThreadSafe属性,pageEncoding属性。
1. 属性contentType的值
JSP页面使用page指令只能为contentType指定一个值,以此确定响应的MIME类型。当用户请求一个JSP页面时,Tomcat服务器负责解释执行JSP页面,并将某些信息发送给客户机的浏览器,以便用户浏览这些信息。如果希望客户机的浏览器用HTML解析器来解析执行这些信息,就可以用page指令指定JSP页面的contentType属性的值为“text/html;charset=GB2312”,例如:
<%@ page contentType=”text/html;charset=GB2312” %>
如果不使用page指令为contentType指定一个值,那么属性“contentType”的默认值是“text/html;charset=ISO-8859-1”。
注:不允许两次使用page指令给contentType属性指定不同的值,下列用法错误:
<%@ page contentType=“text/html;charset=GB2312” %>
<%@page contentType=“application/msword” %>
注:如果想深入了解MIME类型,可以在网络搜索引擎中搜索MIME关键字。
【例1】制作3个JSP页面:A.jsp页面,使用page指令设置contentType属性的值为”text/html;charset=GB2312”,当客户请求A.jsp页面时,客户的浏览器使用HTML解析器来解析执行收到的信息;B.jsp页面,使用page指令设置contentType属性的值为“application/msword”,当客户请求B.jsp页面时,客户的浏览器将使用Word应用程序来解析执行收到的信息;C.jsp页面,使用page指令设定contentType属性的值为“image/jpeg”,当客户请求C.jsp页面时,客户的浏览器将使用图形解析器来解析执行收到的信息。
A.jsp
<%@ page contentType="text/html;Charset=UTF-8" %>
<HTML><BODY bgcolor=cyan>
<FONT size=3>
<P>我在学习page指令
</FONT></BODY></HTML></HTML>
B.jsp
<%@ page contentType="application/msword" %>
<HTML><BODY bgcolor=cyan>
<FONT size=3>
<P>启动Word应用程序
</FONT></BODY></HTML>
C.jsp
<%@ page contentType="image/jpeg" %>
<%@ page import="java.awt.*" %>
<%@ page import="java.io.*" %>
<%@ page import="java.awt.image.*" %>
<%@ page import="java.awt.geom.*" %>
<%@ page import="com.sun.image.codec.jpeg.*" %>
<% int width=260,height=260;
BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g=image.getGraphics();
g.setColor(Color.white);
g.fillRect(0,0,width,height);
Graphics2D g_2d=(Graphics2D)g;
Ellipse2D ellipse=new Ellipse2D.Double(40,80,100,40);
g_2d.setColor(Color.blue);
AffineTransform trans=new AffineTransform();
for(int i=1;i<=12;i++){
trans.rotate(30.0*Math.PI/180,90,100);
g_2d.setTransform(trans);
g_2d.draw(ellipse);
}
g.dispose();
OutputStream outClient=response.getOutputStream();
JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(outClient);
encoder.encode(image);
%>
效果如图所示:
2. 属性import的值
Import属性的作用是为JSP页面引入Java核心包中的类,这样就可以在JSP页面的程序片部分、变量及方法声明部分、表达式部分使用包中的类。可以为该属性指定多个值,该属性的值可以是Java某包中的所有类或一个具体的类。
使用page指令可以为import属性指定几个值,这些值用逗号分隔。例如:
<%@page import=”java.util.*”,”java.io.*”,”java.awt.*”%>
也可以使用多个page指令为import属性指定几个值。例如:
<%@ page import=”java.util.*” %>
<%@ page import=”java.io.* %>
<%@ page import=”java.awt.*” %>
当为import属性指定多个值时,JSP引擎把JSP页面转换成的Java文件中会有以下import语句:
Import java.util.*;
Import java.io.*;
Import java.awt.*;
JSP页面的默认import属性有如下值:”java.lang.*”、”javax.servlet.*”、”havax.servlet.jsp.*”、”javax.servlet.http.*”。Import属性是一个比较特殊的属性,可以被指定多个值。需要特别注意的是,除import属性外,其余属性只能被指定一个值。
3. 属性language的值
Language属性定义JSP页面使用的脚本语言,该属性的值目前只能取“Java”。为language属性指定值的格式如下:
<%@ page language=”java” %>
Language属性的默认值是“Java”。如果在JSP页面没有使用page指令指定该属性的值,那么JSP页面默认有如下page指令:
<%@ page language=”java” %>
4. 属性session
Session属性的值用于设置是否需要使用Tomcat服务器内置的session对象。Session属性的值可以是true或者false,默认属性值是true。
5. 属性buffer
内置输出流对象out负责将服务器的某些信息或运用结果发送到客户端显示,buffer属性用来指定out使用的缓冲区大小或不使用缓冲区。
Buffer属性的默认值是8KB,可以使用page指令修改这个默认值。例如:
<%@ page buffer=”24KB” %>
如果不准备让out流使用缓冲区,可将buffer属性的值设为none。
6. 属性autoFlush
autoFlush属性指定out流的缓冲区被填满时,缓冲区是否自动刷新。
autoFlush可以取值true或false,默认值是true。当autoFlush属性取值为false时,如果out的缓冲区填满,就会出现缓存溢出异常。当buffer的值为none时,autoFlush的值就不能设置成false。
7. 属性isThreadSafe
isThreadSafe属性取值true或false,默认值是true。Tomcat服务器使用多线程技术处理客户的请求,即当多个客户机请求一个JSP页面时,Tomcat服务器为每个客户机启动一个线程,每个线程分别负责执行常驻内存的字节码文件来响应响应客户机的请求。这些线程由Tomcat服务器来管理,将CPU的使用权在各线程之间快速切换,以保证每个线程都有机会执行字节码文件。当isThreadSafe属性值为true时,CPU的使用权在各线程间快速切换,也就是说,即使一个客户机的线程没有执行完毕,CPU的使用权也可能要切换给其他线程。如此轮流,直到各线程执行完毕。当JSP使用page指令将isThreadSafe属性值设置成false时,该JSP页面同一时刻只能处理响应一个客户机的请求,其他客户继续排队等待。也就是说,CPU要保证一个线程将JSP页面执行完毕,才会把CPU使用权切换给其他线程。
二 指令标记include
设计一个Web应用可能需要编写若干个JSP页面,如果这些JSP页面都需要显示某些同样的信息,如每个JSP页面上都可能需要一个导航条,以便用户在各JSP页面之间来回切换,那么每个JSP页面都可以使用include指令标记在页面的适当位置整体嵌入一个相同的文件。
指令标记include的语法如下:
<%@ include file=”文件的URL” %>
该指令标记的作用是在JSP页面上出现该指令的位置处静态嵌入一个文件。被嵌入的文件必须是可访问和可使用的。如果该文件和当前JSP页面在同一Web服务目录中,那么“文件的URL”就是文件的名字;如果该文件在JSP页面所在的Web服务目录的一个子目录中,如image子目录,那么“文件的URL”就是“image/文件的名字”.
所谓静态嵌入,就是Tomcat服务器在编译阶段就完成文件的嵌入操作,即将当前的JSP页面和要嵌入的文件合并成一个新的JSP页面,Tomcat服务器再将这个新的JSP页面转译成Java文件。因此,嵌入文件后,必须保证新合并成的JSP页面符合JSP语法规则,即能够成为一个NSP页面文件。比如,当前JSP页面已经使用page指令设置了contentType属性的值:
<%@ page coontentType=”text/html;Charset=GB2312” %>
若被嵌入的文件也是一个JSP页面,其中也使用page指令为contentType属性设置了值:
<%@ page contentType=”application/msword” %>
那么,合并后的JSP页面就两次使用page指令为contentType属性设置了不同的属性值,导致语法错误,因为JSP页面中的page指令只能为contentType指定一个值。
Tomcat 5.0版本以后的服务器每次都要检查被嵌入的文件是否被修改过。因此,JSP页面成功静态嵌入一个文件后,如果对嵌入的文件进行了修改,那么Tomcat服务器会重新编译JSP页面,即将当前的JSP页面和修改后的文件合并成一个JSP页面,然后Tomcat服务器将这个新的JSP页面转译成Java类文件。
【例 2】在JSP页面静态嵌入一个文本文件Hello.txt,该文本文件的内容是:”祝贺深圳成功举办大运会“。文本文件和当前JSP页面在同一Web服务目录中。
Example3_2.jsp
<%@ page contentType=”text/html;Charset=GB2312” %>
<HTML><BODY bgcolor=yellow>
<H1>
<%@ include file=”Hello.txt” %>
</H1>
</BODY></HTML>
上述example3_2.jsp等价于下面的JSP文件exm.jsp。
Exm.jsp
<%@ page contentType=”text/html;Charset=GB2312” %>
<HTML><BODY bgcolor=yellow>
<H1>祝贺深圳成功举办大运会</H1>
</BODY></HTML>
注:在Tomcat 4 版本中,不允许在include指令标记嵌入的文件中使用page指令指定contentType属性的值。但是在Tomcat 5 后的版本中,在include指令标记嵌入的文件中必须使用page指令指定contentType属性的值,而且指定的值必须与嵌入该文件的JSP页面中的page指令指定的contentType属性的值相同。
三 动作标记include
动作标记是一种特殊的标记,影响JSP运行时的行为。Include动作标记的语法有以下两种格式:
<jsp:include page=”文件的URL”/>
或
<jsp:include page=”文件的URL”>
子标记
</jsp:include>
Include动作标记在JSP页面执行阶段处理所需要的文件,因此JSP页面和它所需要的文件在逻辑和语法上是独立的。注意:当include动作标记不需要子标记时,必须使用上述第一种形式。
尽管include动作标记和include指令标记的作用都是处理所需文件,但是在处理方式和处理时间上是不同的。Include指令标记用嵌入方式处理文件,在编译阶段就处理所需文件,优点是页面的执行速度快;而include动作标记不使用嵌入方式来处理所需文件,在JSP页面运行时才处理文件,也就是说,当Tomcat服务器把JSP页面转译成Java文件时,不把JSP页面中include动作标记所包含的文件与原JSP页面合并一个新的JSP页面,而是告诉Java解释器,这个文件在JSP运行时(Java文件的字节码文件被加载执行)才被处理,其优点是能更灵活地处理所需文件(见后面的param标记),缺点是执行速度要慢一些。Include动作标记要处理的文件如果不是JSP文件,就将文件的内容发送到客户机,由客户机负责执行并显示;如果包含的文件是JSP文件,那么Tomcat服务器就执行这个JSP文件,然后将执行的结果发送到客户机,并由客户既负责显示这些结果。
注:书写include动作标记时要注意“jsp”、“:”、“include”三者之间不要有空格。
【例 3】example3_3.jsp页面包含两个文件:time.jsp和sun.jsp。Time.jsp和example3_3.jsp页面在同一Web服务目录中,sun.jsp在当前Web服务目录的子目录image中。
Example3_3.jsp
<%@ page contentType=”text/html;Charset-GB2312” %>
<HTML><BODY bgcolor=red>
<jsp:include page=”time.jsp”/>
<P>请看一幅图像:<BR/>
<jsp:include page=”images/sun.jsp” />
</BODY></HTML>
Time.jsp
<%@ page contentType=”text/html;Charset=GB2312” %>
<%@ page import=”java.util.Date” %>
<HTML><BODY><FONT size=3>
<P>现在的时间:
<% Date date=new Date();
Out.println(date.toString());
%>
</FONT></BODY></HTML>
Sun.jsp
<%@ page contentType=”text/html;Charset=GB2312” %>
<HTML><BODY>
<IMAGE src=”image/ok.jpg” width=120 height=120>太阳图片</IMAGE>
</BODY></HTML>
注:sun.jsp页面使用的图片文件ok.jpg需保存在当前Web服务目录(chapter3)的image子目录中。
效果如图所示:
四 动作标记pagam
Param动作标记可以作为include、forward动作标记的子标记来使用,该标记以“名字-值”对的形式为这些动作标记提供附加信息。
Param动作标记的格式如下:
<jsp:param name=”名字” value=”指定给name属性的值”/>
当使用include动作标记动态处理所需要的JSP文件时,经常会使用param子标记,以便向动态加载的JSP页面传递必要的值,这也体现出include动作标记比include指令标记更灵活的特点。Include动作标记所要加载的JSP文件可以使用Tomcat服务器提供的request内置对象获取param标记中name属性所提供的值。
【例 4】制作页面example3-4.jsp,使用include动作标记动态加载computer.jsp文件。当computer.jsp文件被加载时,该文件获取include动作标记的param子标记中属性name的值。
Example3_4.jsp
<%@ page contentType="text/html;Charset=GB2312" %>
<HTML><BODY bgcolor=yellow>
<P>加载一个JSP文件,该文件负责计算连续整数之和:
<jsp:include page="computer.jsp">
<jsp:param name="item" value="100" />
</jsp:include>
</BODY></HTML>
Computer.jsp
<%@ page contentType="text/html;Charset=GB2312" %>
<HTML><BODY>
<% String str=request.getParameter("item");
int n=Integer.parseInt(str);
int sum=0;
for(int i=1;i<=n;i++){
sum=sum+i;
}
out.println("<BR>从1~"+n+"的连续和是:</BR>"+sum);
%>
</BODY></HTML>
效果如图所示:
五 动作标记forward
Forword动作标记的作用是,从该标记出现处停止当前JSP页面的继续执行,而转向执行forward动作标记中page属性所指定的JSP页面。
Forward动作标记有两种格式:
<jsp:forward page=”要转向的页面”/>
或
<jsp:forward page=”要转向的页面”>
Param 子标记
</jsp:forward>
需要注意的是,当forward动作标记不需要param字标记时,必须使用上述第一种形式。Forward标记可以使用param动作标记作为子标记,以便向要转向的页面传送信息。Forward动作标记指定的要转向的JSP文件,可以使用Tomcat服务器提供的request内置对象获取param子标记中name属性所提供的值。
【例 5】制作example3_5.jsp页面,使用forward标记转向num1.jsp或num2.jsp页面。在example3_5.jsp页面中随即获取一个1~100之间的整数,该数大于50就转向页面num1.jsp,否则转向页面num2.jsp。Forward动作标记时用param子标记,将example3-5.jsp页面获取的随机数传递给要转向的页面。
Example3_5.jsp
<%@ page contentType="text/html;Charset=GB2312" %>
<HTML><BODY>
<%out.println("根据不同的值转向不同的页面:<BR>");
int n=(int)(Math.random()*100)+1;
if(n>50){
%> <jsp:forward page="num1.jsp">
<jsp:param name="item" value="<%=n %>" />
</jsp:forward>
<%
}
else{
%> <jsp:forward page="num2.jsp">
<jsp:param name="item" value="<%=n %>" />
</jsp:forward>
<%
}
out.println("看不见这句话");
%>
</BODY></HTML>
Num1.jsp
<%@ page contentType="text/html;Charset=GB2312" %>
<HTML><BODY bgcolor=cyan>
<% String str=request.getParameter("item");
int n=Integer.parseInt(str);
out.println("<BR>不大于"+n+"的素数:</BR>");
int i=0,j=0;
for(i=1;i<=n;i++){
for(j=2;j<i;j++){
if(i%j==0)
break;
}
if(j==i)
out.println(","+i);
}
%>
</BODY></HTML>
Num2.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY bgcolor=cyan>
<% String str=request.getParameter("item");
int n=Integer.parseInt(str);
out.println("<BR>不大于"+n+"的奇数:</BR>");
for(int i=1;i<=n;i++){
if(i%2!=0)
out.println(","+i);
}
%>
</BODY></HTML>
效果如图所示:
六 动作标记useBean
该标记用来创建并使用一个JavaBean,它是非常重要的一个动作标记。Sun公司倡导的是:用HTML完成JSP页面的静态部分,用JavaBean完成动态部分,实现真正意义上的静态与动态的分离。
七 Tag文件与Tag标记
一个Web应用中的许多JSP页面可能需要使用某些相同的信息,如都需要使用相同的导航栏、标题等。如果能将许多页面都需要的共同的信息形成一种特殊文件,而且各JSP页面都可以使用这种特殊的文件,那么这样的特殊文件就是可复用的代码。代码复用是软件设计的一个重要方面,代码复用是衡量软件可维护性的重要指标之一。为了更好地维护一个Web应用,JSP页面可以通过自定义标记使用一种特殊的文件:Tag文件(标记),在设计Web应用时,可以通过编写Tab文件来实现代码复用。
1. Tag文件的结构
Tag文件是扩展名为.tag的文本文件,其结构几乎与JSP文件相同,只是扩展名不同。也就是说,一个Tag文件中可以有普通的HTML标记符、某些特殊的指令标记、成员变量和方法、Java程序片和Java表达式等。以下是一个简单的Tab文件:
FirstTag.tag
<HTML><BODY>
<p>这是一个Tab文件,负责计算1~100的连续和
<% int sum=0,i=1;
for(i=1;i<=100;i++){
sum=sum+i;
}
out.println(sum);
%>
</BODY></HTML>
2. Tag标记
当我们编写了一个Tag文件后,也就自定义出了一个标记,该标记的格式如下:
<Tag 文件名字/>
或
<Tag 文件名字 >
标记体
</ Tag 文件名字>
也就是说,一个Tag文件对应一个标记,习惯上称为Tag标记。若干Tag标记组成一个标记库,习惯上称为自定义标记库。
3. Tag标记的使用
Tag文件只供JSP页面使用,用户不能通过浏览器直接请求一个Tag文件。一个JSP页面使用Tag标记来调用相应的Tag文件。
为了能让一个Web应用中的JSP页面使用某些Tag文件,必须把这些Tag文件存放到Tomcat服务器指定的目录中,寄存放到“Web服务目录\WEB-INF\tags”中。其中的WEB-INF和tags都是固定的子目录名称,而tags下的子目录名字可由用户给定。也就是说,tags或其下的子目录是专门存放Tag文件的,而一个Tag文件对应一个Tag标记,因此习惯上称tags或其下的子目录为一个标记库。
一个JSP页面必须使用<taglib>指令标记引入若干个标记库。引入标记库后,JSP页面就可以使用带前缀的Tag标记调用相应的Tag文件,其中的前缀由<taglib>指令中的prefix属性指定。例如:
<前缀:Tag 文件名字/>
前缀可以有效地区分不同标记库中具有相同名字的标记文件。
当使用JSP页面调用一个Tag文件时,Tomcat服务器负责处理相应的Tag文件,也就是说,Tomcat服务器将Tag文件转译成一个Java文件,再将这个Java文件编译生成字节码文件,并将这个字节码文件加载到内存中,然后执行这个字节码文件,就好像它是一个常规的JSP文件一样。
现在用一个例子来说明怎样在JSP页面中调用Tag文件。假设使用的Web服务目录是Tomcat安装目录webapps下的一个子目录chapter3。编写FirstTag.tag和SecondTag.tag两个Tag文件。
FirstTag.tag
<HTML><BODY>
<p>这是一个Tab文件,负责计算1~100的连续和
<% int sum=0,i=1;
for(i=1;i<=100;i++){
sum=sum+i;
}
out.println(sum);
%>
</BODY></HTML>
SecondTag.tag
<p>这是一个Tab文件负责计算20内的素数:
<% int i,j;
for(i=1;i<=20;i++){
for(j=2;j<i;j++){
if(i%j==0)
break;
}
if(j==i)
out.println("<BR>素数:"+i);
}
%>
在chapter3下建立目录结构:chapter3\WEB-INF\tags\tagsTwo,将FirstTag.tag存放在tags目录中,而SecondTag.tag存放在tags的子目录tagsTwo中。
【例6】页面文件example3-6.jsp使用了FirstTag.tag和SecondTag.tag文件。
Example3_6.jsp
<%@ page contentType="text/html;Charset=GB2312" %>
<%@ taglib tagdir="/WEB-INF/tags" prefix="com"%>
<%@ taglib tagdir="/WEB-INF/tags/tagsTwo" prefix="game"%>
<HTML><BODY>
<H3>以下是调用Tag文件的效果:</H3>
<com:FirstTag />
<H3>以下是调用Tag文件的效果:</H3>
<game:SecondTag />
</BODY></HTML>
效果如图所示:
4. Tag文件中的常用指令
与JSP文件类似,Tag文件中也有一些常用指令,这些指令将影响Tag文件的行为。Tag文件中经常使用的指令有tag、taglib、include、attribute、variable。以下将分别讲述上述指令在Tag文件中的作用和用法。
(1)tag指令
Tag文件中的tag指令类似于JSP文件中的page指令。Tag文件通过使用tag指令可以指定某些属性的值,以便从总体上影响标记文件的处理和表示。Tag指令的语法如下:
<%@ tag 属性1=”属性值” 属性2=”属性值” ……属性n=”属性值”>
一个Tag文件中可以使用多个tag指令,因此经常使用多个tag指令为属性指定需要的值:
<%@ tag 属性1=”属性值”>
<%@ tag 属性2=”属性值”>
……
<%@ tag 属性n=”属性值”>
Tag指令可以操作的属性有body-content、language、import、pageEncoding。以下分别讲述怎样设置这些属性的值。
A.body-content属性
我们已经知道,一个Tag文件会对应一个自定义标记,该标记的格式如下:
<Tag 文件名字 />
或
<Tag 文件名字>
标记体
</Tag 文件名字>
JSP文件通过使用该定义标记调用相应的Tag文件,那么JSP文件到底应该使用自定义标记的哪种格式来调用Tag文件呢?
一个Tag文件通过tag指令指定body-content属性的值,以决定Tag标记的使用格式,也就是说,该属性的值可以确定JSP页面使用Tag标记时是否可以有标记体,如果允许有标记体,该属性会给出标记体内容的类型。
Body-content属性值有empty、tagdependent、scriptless,默认值是scriptless。
如果body-content属性的值是empty,那么JSP页面必须使用没有标记体的Tag标记
<Tag 文件名字 />
来调用相应的Tag文件。
如果body-content属性的值是tagdependent或scriptless,那么JSP页面可以使用无标记体或有标记体的Tag标记
<Tag文件名字>
标记体
</Tag文件名字>
来调用相应的Tag文件。如果属性值是scriptless,那么标记体中不能有Java程序片;如果属性值是tagdependent,那么标记体的内容将按纯文本处理。
Tag标记中的标记体由相应的Tag文件负责处理,因此,当JSP页面使用有标记体的Tag标记调用一个Tag文件时,可以通过“标记体”向该Tag文件动态地传递文本数据或必要的JSP指令。
Tag文件通过使用指令
<jsp:doBody />
来获得JSP页面传递过来的“标记体”,也就是说,在一个Tag文件中,<jsp:doBody/>指令被替换成“标记体”的内容。
【例 7】Show.tag文件负责用某种颜色显示文本,example3_7.jsp页面负责调用Show.tag文件,而且通过标记体向Show.tag文件传递文本内容。
Example3_7.jsp
<%@ page contentType="text/html;Charset=GB2312" %>
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
<HTML>
<tags:Show>
我喜欢看足球
</tags:Show>
<tags:Show>
I love this game
</tags:Show>
<tags:Show>
我喜欢看奥运比赛
</tags:Show>
</HTML>
Show.tag
<BODY><P>
<% for(int i=1;i<=3;i++){ %>
<FONT color="red" size="3">
<jsp:doBody />
</FONT>
<% }
%>
</P></BODY>
效果如图所示:
B. Language属性
Language属性的值指定Tag文件使用的脚本语言,目前只能取值Java,其默认值就是Java,因此在编写Tag文件时,没有必要使用tag指令指定language属性的值。
C.import属性
Import属性的作用是为Tag文件引入Java核心包中的类,这样就可以在Tag文件的程序片部分、变量及函数声明部分、表达式部分使用包中的类。Import属性可以取多个值,import属性已经有如下值:”java.lang.*”、”javax.servlet.*”、”javax.servlet.jsp.*”、”javax.servlet.http.*”。
D. pageEncoding属性
该属性指定Tag文件的字符编码,其默认值是ISO-8859-1。Tag文件必须使用ANSI编码保存。
(2)include指令
在Tag文件中也可以使用include指令标记,其使用方法和作用与JSP文件中类似。
【例8】Tag文件Trangle.tag负责计算显示三角形的面积。Example3_8.jsp页面在调用Trangle.tag文件时向Trangle.tag文件传递三角形三边的长度。Example3_8.jsp页面存放在Web服务目录chapter3zhong ,Trangle.tag存放在chapter3\WEB-INF\tags中。
Example3_8.jsp
<%@ page contentType="text/html;Charset=GB2312" %>
<%@ taglib tagdir="/WEB-INF/tags" prefix="computer" %>
<HTML><BODY>
<H3>以下是调用Tag文件的效果:</H3>
<computer:Trangle sideA="3" sideB="4" sideC="5"/>
</BODY></HTML>
Trangle.tag
<p>这是一个Tag文件,负责计算三角形的面积。
<%@ attribute name="sideA" required="true" %>
<%@ attribute name="sideB" required="true" %>
<%@ attribute name="sideC" required="true" %>
<%! public String getArea(double a,double b,double c){
if(a+b>c&&a+c>b&&c+b>a){
double p=(a+b+c)/2.0;
double area=Math.sqrt(p*(p-a)*(p-b)*(p-c));
return "<BR>三角形的面积为:"+area;
}
else{
return("<BR>"+a+","+b+","+c+"不能构成一个三角形,无法计算面积");
}
}
%>
<% out.println("<BR>JSP页面传递过来的三条边:"+sideA+","+sideB+","+sideC);
double a=Double.parseDouble(sideA);
double b=Double.parseDouble(sideB);
double c=Double.parseDouble(sideC);
out.println(getArea(a,b,c));
%>
效果如图所示:
小结
1. JSP页面使用page指令可以为属性contentType指定几个值?
答:JSP页面使用page指令只能为contentType指定一个值
2. JSP页面使用page指令可以为import属性指定多个值吗?
答:可以为该属性指定多个值
3. Include指令标记和include动作标记有何不同?
答:在处理方式和处理时间上是不同的。Include指令标记用嵌入方式处理文件,在编译阶段就处理所需文件,优点是页面的执行速度快;而include动作标记不使用嵌入方式来处理所需文件,在JSP页面运行时才处理文件,也就是说,当Tomcat服务器把JSP页面转译成Java文件时,不把JSP页面中include动作标记所包含的文件与原JSP页面合并一个新的JSP页面,而是告诉Java解释器,这个文件在JSP运行时(Java文件的字节码文件被加载执行)才被处理,其优点是能更灵活地处理所需文件(见后面的param标记),缺点是执行速度要慢一些。
4. Param动作标记经常作为哪些标记的子标记,有何作用?
答:param动作标记可以作为include、forward动作标记的子标记来使用,该标记以“名字-值”对的形式为这些动作标记提供附加信息。
5. Tag文件应当存放在怎样的目录中?
答:存放到“Web服务目录\WEB-INF\tags”中
6. 用户可以使用浏览器直接访问一个Tag文件吗?
答:用户不能通过浏览器直接请求一个Tag文件
7. JSP页面怎样调用一个Tag文件?
答:JSP页面可以使用带前缀的Tag标记调用相应的Tag文件
8. 编写两个Tag文件Rect.tag和Circle.tag。Rect.tag负责计算矩形的面积,Circle.tag负责计算圆的面积。编写一个JSP页面,该JSP页面使用Tag标记调用Rect.tag和Circle.tag。调用Rect.tag时,向其传递矩形的两个边的长度;调用Circle.tag时,向其传递圆的半径。
8.Jsp
<%@ page contentType="text/html;Charset=GB2312" %>
<%@ taglib tagdir="/WEB-INF/tags" prefix="rect"%>
<%@ taglib tagdir="/WEB-INF/tags" prefix="circle"%>
<HTML><BODY>
<H3>以下是矩形的面积:</H3>
<rect:Rect length="4" width="3"/>
<H3>以下是圆的面积:</H3>
<circle:Circle radius="4"/>
</BODY></HTML>
Rect.tag
<p>这是一个Tag文件,负责计算矩形的面积。
<%@ attribute name="length" required="true" %>
<%@ attribute name="width" required="true" %>
<%! public String getArea(double a,double b){
double area=a*b;
return "<BR>矩形的面积为:"+area;
}
%>
<% out.println("<BR>JSP页面传递过来的两条边:"+length+","+width);
double a=Double.parseDouble(length);
double b=Double.parseDouble(width);
out.println(getArea(a,b));
%>
Circle.tag
<p>这是一个Tag文件,负责计算圆的面积。
<%@ attribute name="radius" required="true" %>
<%! public String getArea(double a){
double area=3.14159265*a*a;
return "<BR>圆的面积为:"+area;
}
%>
<% out.println("<BR>JSP页面传递过来的半径:"+radius);
double a=Double.parseDouble(radius);
out.println(getArea(a));
%>