JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
JSP 2.0技术手册
作者:林上杰、林康司
出版:电子工业出版社
内容简介:
本书图文并茂,以丰富的实例为引导,全面介绍了主流的 Java Web 开发技术——
JSP 2.0,重点介绍Java在展示层的两项重要技术:Java Servlet与JavaServer Pages。
它们是最重要的Java 核心技术。对这两项技术的深入了解,将有助于您未来对于
JavaServer Faces(JSF)技术以及Java Web Services技术的学习。
注:
本内容仅供学习研究参考,为尊重作者劳动成果及版权,请购买原版
书籍。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
第一章 安装执行环境
1-1 安装J2SDK 1.4.2
第一步:执行j2sdk-1_4_2_03-windows-i586-p.exe(见图1-2);
图1-2 执行j2sdk-1_4_2_03-windows-i586-p.exe
先按【Next】,选择【I accept the terms in the license agreement】后,再按 【Next】。
第二步:选择安装路径及安装内容(见图1-3);
图1-3 选择安装路径及安装内容
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
一般来说,我们通常都默认安装在C:/j2sdk1.4.2_03 的目录下,假若你要安装在其他路径时,
请按【Change】,改变J2SDK 安装路径。确认无误后,再按【Next】。
随后开始安装Java Plug-in至浏览器上,一般都选择【Microsoft Internet Explorer】。再按
下【Install】,正式开始执行安装程序,假若安装成功后,你会看到如图1-4。
图1-4 成功安装J2SDK 1.4.2_03
第三步:设定J2SDK 1.4.2_03(见图1-5);
从【开始】→【设置】→【控制面板】→【系统】→【高级】→【环境变量】→【系统变量】,
然后到【新建】。
JAVA_HOME = C:/j2sdk1.4.2_03
PATH = %JAVA_HOME%/bin
CLASSPATH = C:/j2sdk1.4.2_03/lib/tools.jar;C:/j2sdk1.4.2_03/
lib/dt.jar;
注意
1. CLASSPATH 的设定中,分号(;)用来分开两路径,切勿任意空格;
2. CLASSPATH 的设定中,分号的最后还有一个点“.”。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图1-5 设定J2SDK 之CLASSPATH
补充
不论Windows 2000 或Windows XP 皆可依上述方法设定。
第四步:测试J2SDK。
撰写一个HelloWorld.java 程序,放置在C:/HelloWorld.java 中。
HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
打开命令提示符,在C:/ 下输入javac HelloWorld.java,然后再输入java HelloWorld,执行
HelloWorld 程序,假若顺利成功,则会显示“Hello World”,如图1-6 所示。
图1-6 编译且执行HelloWorld 程序
成功安装J2SDK 1.4.2_03 之后,紧接下来安装Tomcat 5.0.16。
1-2 安装Tomcat 5.0.16
Tomcat 目前版本为5.0.16,它是由JavaSoft 和Apache 开发团队共同提出合作计划( Apache
Jakarta Project )下的产品。Tomcat 能支持Servlet 2.4 和JSP 2.0 并且是免费使用。
Tomcat 5.0.16 可以从 http://jakarta.apache.org/tomcat/index.html 网站自行免费下载,或
者可以直接使用本书CD 光盘中的Tomcat 5.0.16,软件名称为:jakarta-tomcat-5.0.16.exe。
第一步:执行jakarta-tomcat-5.0.16.exe(见图1-7);
先按【Next】,选择【I Agree】后,再按【Next】。
第二步:选择安装路径及安装内容(见图1-8);
通常我们会选择完全安装(Full),即如图1-8。在图1-9【Tomcat】的选项中,主要有:Core、Service、
Source Code和Documentation,假若选择安装Service时,尔后我们可以利用Windows 的服务(控制
面板 |管理工具 |服务)来设定重新开机启动时,Tomcat能够自动启动。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图1-7 执行jakarta-tomcat-5.0.16.exe
图1-8 选择安装内容
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图1-9 选择安装Service
选择完全安装后,按【Next】。开始选择安装路径,如图1-10 所示。
图1-10 选择安装路径
第三步:设定Tomcat Port 和Administrator Login(见图1-11);
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图1-11 设定Tomcat Port 和Administrator Login
第四步:设定Tomcat 使用的JVM(见图1-12);
图1-12 选择Tomcat 使用的JVM
确认无误后,按下【Install】,正式开始执行安装程序。安装成功后,会看到如图1-13的结果。
假若你勾选了【Run Apache Tomcat】,按下【Finish】之后,会直接启动Tomcat 5.0.16,然后
在你计算机的右下角,会出现绿色箭头的符号,如图1-14。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图1-13 成功安装Tomcat 5.0.16
图1-14 Tomcat 图标
第五步:测试Tomcat。
打开浏览器,如IE,输入 http://localhost:8080,假若Tomcat安装成功,则会看到如图1-15的
情形。
图1-15 连接 http://localhost:8080/,测试Tomcat 5.0.16
本书“第十二章:JSP 执行环境与开发工具”,对于Tomcat 的使用及设定有更详细的介绍。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
1-3 安装JSPBook 站台范例
读者可以在CD 光盘中找到本书的范例,程序文件名为JSPBook.war。
第一步:安装JSPBook.war;
安装的方法很简单,只要将JSPBook.war 移至{Tomcat_Install}/webapps/目录下(例如:
C:/Program Files/Apache Software Foundation/Tomcat 5.0/webapps/JSPBook.war) , 然后
JSPBook.war 会自动被Tomcat 解压缩成JSPBook 的目录,如图1-16。
图1-16 安装JSPBook.war
第二步:设定JSPBook 站台;
在Tomcat 上建立一个JSPBook 站台时,我们须修改Tomcat 的server.xml 文件,server.xml 位
于{Tomcat_Install}/conf/server.xml(例如:C:/Program Files/Apache Software Foundation/
Tomcat 5.0/conf/server.xml)。
server.xml
………
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
crosscontext="true" reloadable="true" >
这部分主要是设定JSPBook 站台, 其中path="/JSPBook"代表网域名称, 即
http://IP_DomaninName/JSPBook ; docBase="JSPBook" 代表站台的目录位置, 即
{Tomcat_Install}/webapps/JSPBook;debug 则是设定debug level,0 表示提供最少的信息,9 表
示提供最多的信息;reloadable则表示Tomcat在执行时,当class、web.xml被更新过时,都会自
动重新加载,不需要重新启动Tomcat。
注意
… 的位置必须在
… 之间,不可任意更动位置。
第三步:执行JSPBook 站台(见图1-17);
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图1-17 执行JSPBook 站台
第四步:JSPBook 站台目录结构。
JSPBook 目录下包含:
(1) 各章节的HTML/JSP 程序;
(2) dist 目录:存放在JSPBook 站台压缩后的JSPBook.war;
(3) build.xml:Ant 文件;
(4) WEB-INF 目录:包含 /classes、/lib、/tags 和 /src;
(5) src 目录:存放范例的源程序,如:JavaBean、Filter、Servlet,等等;
(6) Images 目录:存放范例程序的图片。
图1-18 为JSPBook 站台目录结构。
图1-18 JSPBook
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
1-4 安装Ant 1.6
修改JSP 程序时,Tomcat 会自动将JSP 重新转译为Servlet,并且编译Servlet。但是,假
若修改Servlet、JavaBean 或Filter 时,我们就必须自行先编译它们,然后再将它们重新部署
至WEB-INF/classes 下。
为了方便编译这些程序,笔者提供JSPBook 站台的build.xml文件,因此,建议读者先安装Ant
1.6,并且学习使用Ant。
目前Ant 的最新版本为1.6,读者可以自行至 http://ant.apache.org 下载最新版本,如
图1-19 所示, 或者直接使用本书CD 光盘中的Ant 1.6 , 软件名称为:
apache-ant-1.6.0-bin.zip。
第一步:将apache-ant-1.6.0-bin.zip 解压缩;
解压缩apache-ant-1.6.0-bin.zip 之后,在apache-ant-1.6.0-bin 目录下会有一目录
apache-ant-1.6.0,然后将apache-ant-1.6.0整个目录搬移至C:/ 底下。
第二步:设定Ant 1.6(见图1-20);
从【开始】→【设定】→【控制面板】→【系统】→【高级】→【环境变量】 →【系统变量】,
然后到【新建】。
ANT_HOME = C:/apache-ant-1.6.0
PATH = %ANT_HOME%/bin
第三步:测试Ant 1.6;
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图1-19 http://ant.apache.org
图1-20 设定Ant 1.6
打开命令提示符,输入 ant –version,假若执行成功,则会有如图1-21 所示的结果。
图1-21 测试Ant 1.6
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
第四步:使用Ant 1.6 编译JSPBook/WEB-INF/src 中的程序。
要编译修改过的JSPBook/WEB-INF/src 中的程序时,首先打开命令提示符,移至JSPBook 站台
的所在目录,例如:C:/Program Files/Apache Software Foundation/Tomcat 5.0/webapps/JSPBook。
然后执行ant,它会先自动找到JSPBook/build.xml文件,根据build.xml的设定,编译C:/Program
Files/Apache Software Foundation/Tomcat 5.0/webapps/JSPBook/WEB-INF/src目录下所有的Java
源文件,然后将产生的类文件存放至C:/Program Files/Apache Software Foundation/Tomcat
5.0/webapps/JSPBook/WEB-INF/classes 目录下。图1-22 为执行ant 指令的结果。
图1-22 执行ant 指令
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
第二章 Servlet 2.4 简介
2-1 Servlet 简介
自1997 年3月Sun Microsystems 公司所组成的JavaSoft部门将Servlet API 定案以来,推出
了Servlet API 1.0。就当时功能来说,Servlet 所提供的功能包含了当时的CGI (Common Gateway
Interface)与Netscape Server API (NSAPI)之类产品的功能。
发展至今,Servlet API的最新版本为2.4版。它依旧是一个具有跨平台特性、100% Pure Java
的Server-Side 程序,它相对于在Client 端执行的Applet。Servlet 不只限定于HTTP 协议,开发
人员可以利用Servlet自定义或延伸任何支持Java的Server —— 包括 Web Server、Mail Server、
Ftp Server、Application Server 或任何自定义的Server。
Servlet有以下优点:
● 可移植性(Portability)
Servlet 皆是利用Java 语言来开发的,因此,延续Java 在跨平台上的表现,不论Server 的操
作系统是Windows、Solaris、Linux、HP-UX、FreeBSD、Compaq Tru 64、AIX 等等,都能够将我们
所写好的Servlet程序放在这些操作系统上执行。借助Servlet的优势,就可以真正达到Write Once,
Serve Anywhere 的境界,这正是从事Java 程序员最感到欣慰也是最骄傲的地方。
当程序员在开发Applet 时,时常为了“可移植性”(portability)让程序员感到绑手绑脚的,
例如:开发Applet 时,为了配合Client端的平台 ( 即浏览器版本的不同,plug-in 的JDK版本也
不尽相同 ),达到满足真正“跨平台”的目的时,需要花费程序员大量时间来修改程序,为的就是
能够让用户皆能够执行。但即使如此,往往也只能满足大部分用户,而其他少数用户,若要执行
Applet,仍须先安装合适的JRE (Java Runtime Environment)。
但是Servlet 就不同了,主要原因在于Servlet 是在Server 端上执行的,所以,程序员只要专
心开发能在实际应用的平台环境下测试无误即可。除非你是从事做Servlet Container 的公司,否
则不须担心写出来的Servlet 是否能在所有的Java Server 平台上执行。
● 强大的功能
Servlet 能够完全发挥Java API 的威力,包括网络和URL 存取、多线程 (Multi-Thread)、影像
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
处理、RMI (Remote Method Invocation)、分布式服务器组件 (Enterprise Java Bean)、对象序列
化 (Object Serialization) 等。若想写个网络目录查询程序,则可利用JNDI API;想连接数据库,
则可利用JDBC,有这些强大功能的API 做后盾,相信Servlet 更能够发挥其优势。
● 性能
Servlet 在加载执行之后,其对象实体(instance)通常会一直停留在Server 的内存中,若有请
求(request)发生时,服务器再调用Servlet来服务,假若收到相同服务的请求时,Servlet会利用
不同的线程来处理,不像CGI 程序必须产生许多进程 (process)来处理数据。在性能的表现上,大
大超越以往撰写的CGI 程序。最后补充一点,那就是Servlet 在执行时,不是一直停留在内存中,
服务器会自动将停留时间过长一直没有执行的Servlet 从内存中移除,不过有时候也可以自行写程
序来控制。至于停留时间的长短通常和选用的服务器有关。
● 安全性
Servlet也有类型检查(Type Checking)的特性,并且利用Java的垃圾收集(Garbage Collection)
与没有指针的设计,使得Servlet 避免内存管理的问题。
由于在Java的异常处理(Exception-Handling)机制下,Servlet能够安全地处理各种错误,不会
因为发生程序上逻辑错误而导致整体服务器系统的毁灭。例如:某个Servlet发生除以零或其他不合
法的运算时,它会抛出一个异常(Exception)让服务器处理,如:记录在记录文件中(log file)。
2-2 First Servlet Sample Code
HelloServlet.java
package tw.com.javaworld.CH2;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class HelloServlet extends HttpServlet {
//Initialize global variables
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
//Process the HTTP Get request
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=GB2312");
PrintWriter out = response.getWriter();
out.println("");
out.println("
CH2 - HelloServlet");
out.println("");
out.println(" Hello World
");
out.println("大家好");
out.println("");
out.println("");
out.close();
}
//Get Servlet information
public String getServletInfo() {
return "tw.com.javaworld.CH2.HelloSerlvet Information";
}
}
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
注意:HelloServlet.java 范例程序位于JSPBook/WEB-INF/src/tw/com/javaworld/CH2,其中
JSPBook 范例程序的安装方法,请参见1-3节“安装JSPBook站台范例” 和1-4 节“安装Ant 1.6”。
一开始我们必须导入(import) javax.servlet.*、javax.servlet.http.*。
javax.servlet.* :存放与HTTP 协议无关的一般性Servlet 类;
javax.servlet.http.* :除了继承javax.servlet.* 之外,并且还增加与HTTP协议有关的功能。
所有Servlet 都必须实现javax.servlet.Servlet 接口(Interface),但是通常我们都会从
javax.servlet.GenericServlet 或javax.servlet.http.HttpServlet 择一来实现。若写的Servlet
程序和HTTP 协议无关,那么必须继承GenericServlet 类;若有关,就必须继承HttpServlet 类。
javax.servlet.* 里的ServletRequest和ServletResponse 接口提供存取一般的请求和响应;
而javax.servlet.http.* 里的HttpServletRequest 和HttpServletResponse 接口,则提供HTTP
请求及响应的存取服务。
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
这个例子中,一开始和Applet 一样,也有init( )的方法。当Servlet 被Container 加载后,
接下来就会先执行init( )的内容,因此,我们通常利用init( )来执行一些初始化的工作。
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("");
out.println("
CH2 - HelloServlet");
out.println("");
out.println("Hello World
");
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
out.println("大家好");
out.println("");
out.println("");
out.close();
}
Servlet 可以利用HttpServletResponse 类的setContentType( )方法来设定内容类型,我们要
显示为HTML 网页类型,因此,内容类型设为"text/html",这是HTML 网页的标准MIME 类型值。之
后,Servlet用getWriter( )方法取得PrintWriter类型的out对象,它与PrintSteam 类似,但是
它能对Java 的Unicode 字符进行编码转换。最后,再利用out 对象把 "Hello World" 的字符串显
示在网页上。
public void destroy( ){
…………
…………. Servlet 结束时,会自动调用执行的程序
………….
}
若当Container 结束Servlet时,会自动调用destroy( ),因此,我们通常利用destroy( )来
关闭资源或是写入文件,等等。
编译HelloServlet.java 的方法:
(1) 将servlet-api.jar 加入至CLASSPATH之中,直接使用javac 来编译HelloServlet.java。
其中servlet-api.jar 可以在{Tomcat_Install}/common/lib 找到。
(2) 直接使用Ant 方式编译HelloServlet.java,请参见1-4 节“安装Ant 1.6”。
编译好HelloServlet.java 之后,再来设定web.xml,如下:
HelloServlet
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
tw.com.javaworld.CH2.HelloServlet
HelloServlet
/HelloServlet
最后,HelloServlet.java 的执行结果如图2-1 所示。
图2-1 HelloServlet.java 的执行结果
顺利完成第一个Servlet 程序后,不知道读者有没有发现,在HelloServlet.java 主程序中,
其实大部分都是一些用来显示HTML 的out.println("….")程序代码,这就是Servlet 用在开发
Web-based 系统时最麻烦的地方。假若Servlet 要显示表格统计图时,我想那时候程序员一定会疯
掉,因为你会发现,其实你所有的时间都在out.println( ),因此,Servlet 适合在简单的用户接
口(User Interface)系统中。不过,幸好有JSP 技术来解决这项极为不方便的问题。
2-3 Servlet 的生命周期
当Servlet加载Container 时,Container可以在同一个JVM 上执行所有Servlet,所以Servlet
之间可以有效地共享数据,但是Servlet 本身的私有数据亦受Java 语言机制保护。
Servlet 从产生到结束的流程如图2-2 所示。
(1) 产生Servlet,加载到Servlet Engine中,然后调用init( )这个方法来进行初始化工作。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
(2) 以多线程的方式处理来自Client 的请求。
(3) 调用destroy( )来销毁Servlet,进行垃圾收集 (garbage collection)。
Servlet 生命周期的定义,包括如何加载、实例化、初始化、处理客户端请求以及如何被移除。
这个生命周期由javax.servlet.Servlet 接口的init ( )、service( )和destroy( )方法表达。
图2-2 Servlet 从产生到结束的流程
1. 加载和实例化
当Container一开始启动,或是客户端发出请求服务时,Container会负责加载和实例化一个Servlet。
2. 初始化
Servlet 加载并实例化后,再来Container必须初始化Servlet。初始化的过程主要是读取配置
信息(例如JDBC连接)或其他须执行的任务。我们可以借助ServletConfig 对象取得Container 的
配置信息,例如:
HelloServlet
tw.com.javaworld.CH2.HelloServlet
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
user
browser
其中user 为初始化的参数名称;browser 为初始化的值。因此,可以在HelloServlet程序中使
用ServletConfig 对象的getInitParameter("user")方法来取得browser。
3. 处理请求
Servlet 被初始化后,就可以开始处理请求。每一个请求由ServletRequest 对象来接收请求;
而ServletResponse 对象来响应该请求。
4. 服务结束
当Container 没有限定一个加载的Servlet 能保存多长时间,因此,一个Servlet 实例可能只
在Container 中存活几毫秒,或是其他更长的任意时间。一旦destroy( )方法被调用时,Container
将移除该Servlet,那么它必须释放所有使用中的任何资源,若Container 需要再使用该Servlet
时,它必须重新建立新的实例。
2-4 Servlet 范例程序
为了说明Servlet 和网页是如何沟通的,笔者在此举一个Sayhi 的范例程序。这个范例程序分
为两部分:Sayhi.html 和Sayhi.java。
在Sayhi.html 中,用户可以填入姓名,然后按下【提交】后,将数据传到Sayhi.java做处理,
而Sayhi.java 负责将接收到的数据显示到网页上。
Sayhi.html
CH2 - Sayhi.html
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
Servlet 范例程序
Sayhi.html 的执行结果如图2-3 所示。
图2-3 Sayhi.html 的执行结果
Sayhi.java
package tw.com.javaworld.CH2;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
public class Sayhi extends HttpServlet {
//Initialize global variables
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
//Process the HTTP Get request
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=GB2312");
PrintWriter out = response.getWriter();
request.setCharacterEncoding("GB2312");
String Name = request.getParameter("Name");
out.println("");
out.println("
CH2 - Sayhi");
out.println("");
out.println("Hi:"+Name);
out.println("");
out.println("");
out.close();
}
//Get Servlet information
public String getServletInfo() {
return "tw.com.javaworld.CH2.Sayhi Information";
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
}
public void destroy() {
}
}
从Sayhi.java的程序当中,可以发现Servlet是利用HttpServletRequest类的getParameter( )
方法来取得由网页传来的数据。不过数据通过HTTP协议传输时会被转码,因此在接收时,必须再做转
码的工作,才能够正确地接收到数据。下面这段程序是做转码的动作:
request.setCharacterEncoding("GB2312");
编译Sayhi.java 之后,再来设定web.xml:
Sayhi
tw.com.javaworld.CH2.Sayhi
Sayhi
/CH2/Sayhi
执行 http://localhost:8080/JSPBook/CH2/Sayhi,结果如图2-4 所示。
图2-4 Sayhi.html 按下【提交】后,经过Sayhi.java 处理后的结果
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
2-5 Servlet 2.4 的新功能
2003 年11 月底,J2EE 1.4 规范正式发布,Servlet也从原本的2.3版升级至2.4版。其中主要
新增的功能有以下三点:
(1) web.xml DTD 改用XML Schema;
(2) 新增Filter 四种设定;
(3) 新增Request Listener、Event 和Request Attribute Listener、Event。
2-5-1 web.xml 改用XML Schema
Servlet 在2.4 版之前,web.xml 都是使用DTD(Document Type Definition)来定义XML 文件内
容结构的,因此,Servlet 2.3 版 web.xml 一开始的声明如下:
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
" http://java.sun.com/dtd/web-app_2_3.dtd">
…………
到了Servlet 2.4 版之后,web.xml 改为使用XML Schema,此时web.xml 的声明如下:
xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
xsi:schemaLocation=" http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
…………
由DTD 改为Schema,主要加强两项功能:
(1) 元素可不依照顺序设定;
(2) 更强大的验证机制。
下面的范例,在Servlet 2.3 版是不合规则的web.xml 文件:
...
ServletA
tw.com.javaworld.servlet.ServletA
ServletA
/ServletA/*
ServletB
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
tw.com.javaworld.servlet.ServletB
ServletB
/ServletB /*
...
因为
元素必须在元素之后,因此,上述的范例要改为:
...
ServletA
tw.com.javaworld.servlet.ServletA
ServletB
tw.com.javaworld.servlet.ServletB
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
ServletA
/ServletA/*
ServletB
/ServletB /*
...
不过在Servlet 2.4版之后,原来的范例也算是一个合法的web.xml文件,不再须注意元素的顺序。
除此之外,Servlet 2.4 版web.xml 的Schema 更能提供强大的验证机制,例如:
(1) 可检查元素的值是否为合法的值。例如:的元素,其值只
能为REQUEST、FORWARD、INCLUDE 和ERROR,如下所示:
Hello
/CH11/*
REQUEST
FORWARD
若元素的值不为上述四种时,此web.xml 将会发生错误。
(2) 可检查如Servlet、Filter 或EJB-ref 等等元素的名称是否惟一。例如:
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
ServletA
tw.com.javaworld.servlet.ServletA
ServletA
tw.com.javaworld.servlet.ServletB
(3) 可检查元素值是否为合法文字字符或数字字符。例如:
Hello
/CH11/*
2-5-2 新增Filter 四种设定
Servlet 2.3 版新增了Filter的功能,不过它只能由客户端发出请求来调用Filter,但若使用
RequestDispatcher.forward( )或RequestDispatcher.include( )的方法调用Filter 时,Filter
却不会执行。因此,在Servlet 2.4版中,新增Filter的设定来解决这个问题。有关
Filter 的部分在本书“第十一章:Filter 与Listener”有更详细的介绍。
Servlet 2.4 版新增的Filter 四种设定为:REQUEST、FORWARD、INCLUDE 和ERROR。假若你有
一个SimpleFilter,它只允许由客户端发出请求或由RequestDispatcher.include( )的方式来调用
执行SimpleFilter,此时SimpleFilter 的设定如下:
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
SimpleFilter
tw.com.javaworld.CH11.SimpleFilter
SimpleFilter
/CH11/*
REQUEST
INCLUDE
2-5-3 新增Request Listener、Event 和Request Attribute Listener、Event
在Servlet 2.3 版中,新增许多的Listener 接口和Event 类(见表2-1):
表2-1
Listener 接口 Event 类
ServletContextListener ServletContextEvent
ServletContextAttributeListener ServletContextAttributeEvent
HttpSessionListener HttpSessionEvent
HttpSessionActivationListener
HttpSessionAttributeListener
在Servlet 2.4版陆续又多新增Request Listener、Event和Request Attribute Listener、Event
(见表2-2):
表2-2
Listener 接口 Event 类
ServletRequestListener ServletRequestEvent
ServletRequestAttributeListener ServletRequestAttributeEvent
这部分在“第十一章:Filter 与Listener”中有更详细的介绍。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
2-5-4 Servlet 2.4 的其他变更
Servlet 2.4 其他较显著的变更如:
(1) 取消SingleThreadModel接口。当Servlet实现SingleThreadModel 接口时,它能确保同时间
内,只能有一个thread 执行此Servlet。
(2) 可以为Servlet。例如:
Index
tw.com.javaworld.IndexServlet
Index
/*
Index
(3) ServletRequest 接口新增一些方法,如:
public String getLocalName( );
public String getLocalAddr( );
public int getLocalPort( );
public int getRemotePort( );
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
第三章 JSP 2.0 简介
3-1 JavaServer Pages 技术
JavaServer Pages技术是一个纯Java 平台的技术,它主要用来产生动态网页内容,包括:HTML、
DHTML、XHTML 和XML。JavaServer Pages技术能够让网页人员轻易建立起功能强大、有弹性的动态
内容。
JavaServer Pages 技术有下列优点:
● Write Once, Run Anywhere 特性
作为Java 平台的一部分,JavaServer Pages 技术拥有Java语言“一次编写,各处执行”的特
点。随着越来越多的供货商将JavaServer Pages 技术添加到他们的产品中,您可以针对自己公司
的需求,做出审慎评估后,选择符合公司成本及规模的服务器,假若未来的需求有所变更时,更换
服务器平台并不影响之前所投下的成本、人力所开发的应用程序。
● 搭配可重复使用的组件
JavaServer Pages技术可依赖于重复使用跨平台的组件(如:JavaBean或Enterprise JavaBean
组件)来执行更复杂的运算、数据处理。开发人员能够共享开发完成的组件,或者能够加强这些组
件的功能,让更多用户或是客户团体使用。基于善加利用组件的方法,可以加快整体开发过程,也
大大降低公司的开发成本和人力。
● 采用标签化页面开发
Web 网页开发人员不一定都是熟悉Java 语言的程序员。因此,JSP 技术能够将许多功能封装起
来,成为一个自定义的标签,这些功能是完全根据XML 的标准来制订的,即JSP 技术中的标签库(Tag
Library)。因此,Web 页面开发人员可以运用自定义好的标签来达成工作需求,而无须再写复杂的
Java 语法,让Web 页面开发人员亦能快速开发出一动态内容网页。
今后,第三方开发人员和其他人员可以为常用功能建立自己的标签库,让Web 网页开发人员能
够使用熟悉的开发工具,如同HTML 一样的标签语法来执行特定功能的工作。本书将在“第十五章:
JSP Tag Library”和“第十六章:Simple Tag 与Tag File”中详细地为各位介绍如何制作标签。
● N-tier 企业应用架构的支持
有鉴于网际网络的发展,为因应未来服务越来越繁杂的要求,且不再受地域的限制,因此,
必须放弃以往Client-Server的Two-tier 架构,进而转向更具威力、弹性的分散性对象系统。由于
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
JavaServer Page 技术是Java 2 Platform Enterprise Edition (J2EE) (相关信息请参阅
www.javasoft.com/products/j2ee)集成中的一部分,它主要是负责前端显示经过复杂运算后之结果
内容,而分散性的对象系统则是主要依赖EJB ( Enterprise JavaBean )和JNDI ( Java Naming and
Directory Interface )构建[1]而成。
3-2 What is JSP
JSP( JavaServer Pages )是由Sun 公司倡导、许多别的公司参与一起建立的一种新动态网页
技术标准,类似其他技术标准,如ASP、PHP 或是ColdFusion,等等。
在传统的网页HTML 文件( *.htm,*.html )中加入Java程序片段( Scriptlet )和JSP标签,构
成了JSP 网页(*.jsp)。Servlet/JSP Container 收到客户端发出的请求时,首先执行其中的程序片
段,然后将执行结果以HTML格式响应给客户端。其中程序片段可以是:操作数据库、重新定向网页
以及发送 E-Mail 等等,这些都是建立动态网站所需要的功能。所有程序操作都在服务器端执行,
网络上传送给客户端的仅是得到的结果,与客户端的浏览器无关,因此,JSP 称为Server-Side
Language。
3-3 JSP 与Servlet 的比较
Sun 公司首先发展出Servlet,其功能非常强大,且体系设计也很完善,但是它输出HTML 语法
时,必须使用out.println( )一句一句地输出,例如下面一段简单的程序:
out.println("");
out.println("demo1");
out.println(" Hello World
");
out.println("");
out.println("大家好");
out.println("");
out.println("");
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
由于这是一段简单的Hello World 程序,还看不出来其复杂性,但是当整个网页内容非常复杂
时,那么你的Servlet 程序可能大部分都是用out.println( )输出HTML 的标签了!
后来Sun 公司推出类似于ASP 的嵌入型Scripting Language,并且给它一个新的名称:
JavaServer Pages,简称为JSP。于是上面那段程序改为:
www.javaworld.com.tw – 台湾Java 论坛
<%
out.println(" Hello World
");
out.println("大家好");
%>
这样就简化了Web 网页程序员的负担,不用为了网页内容编排的更动,又需要由程序员来做修
改。
3-4 JSP 的执行过程
在介绍JSP 语法之前,先向读者说明一下JSP 的执行过程(见图3-1)。
(1) 客户端发出Request (请求);
(2) JSP Container 将JSP 转译成Servlet 的源代码;
(3) 将产生的Servlet 的源代码经过编译后,并加载到内存执行;
(4) 把结果Response (响应)至客户端。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图3-1 JSP 的执行过程
一般人都会以为JSP 的执行性能会和Servlet 相差很多,其实执行性能上的差别只在第一次的
执行。因为JSP 在执行第一次后,会被编译成Servlet 的类文件[玉玉2],即为XXX.class,当再重
复调用执行时,就直接执行第一次所产生的Servlet,而不用再重新把JSP编译成Servlet。因此,
除了第一次的编译会花较久的时间之外,之后JSP 和Servlet 的执行速度就几乎相同了。
在执行JSP 网页时,通常可分为两个时期:转译时期(Translation Time)和请求时期(Request
Time)(见图3-2)。
转译时期:JSP 网页转译成Servlet 类。
请求时期:Servlet 类执行后,响应结果至客户端。
补充
转译期间主要做了两件事情:将JSP 网页转译为Servlet 源代码(.java),此段称为转译时
期(Translation time);将Servlet 源代码(.java)编译成Servlet 类(.class),此段称为
编译时期(Compilation time)。
图3-2 转译时期与请求时期程序图
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
当JSP 网页在执行时,JSP Container 会做检查的工作,若发现JSP 网页有更新修改时,JSP
Container 才会再次编译JSP 成Servlet;JSP 没有更新时,就直接执行前面所产生的Servlet。
笔者在这里以Tomcat 为例,看看Tomcat 如何将JSP 转译成Servlet。首先笔者写一个简单的
JSP 网页 —— HelloJSP.jsp:
HelloJSP.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ taglib prefix="c" uri=" http://java.sun.com/jsp/jstl/core" %>
CH3 - HelloJSP.jsp
JSP 将会被转译为 Servlet
<%!
int k = 0;
%>
<%
String name = "browser";
out.println("大家好 !!");
%>
<%= name %>
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
当执行HelloJSP.jsp 时,Tomcat 会将它先转译为Servlet。这个Servlet 程序是放在
{Tomcat_Install}/Apache Software Foundation/Tomcat 5.0/ work/Catalina/localhost/JSPBook/
org/apache/jsp/CH3目录下的HelloJSP_jsp.java和HelloJSP_jsp.class。其中HelloJSP_jsp.java
就是HelloJSP.jsp 所转译的Servlet 源代码,它的程序如下:
HelloJSP_jsp.java
package org.apache.jsp.CH3;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class HelloJSP_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
int k = 0;
private static java.util.Vector _jspx_dependants;
private org.apache.jasper.runtime.TagHandlerPool _ jspx_tagPool_c_out_value;
public java.util.List getDependants() {
return _jspx_dependants;
}
public void _jspInit() {
_jspx_tagPool_c_out_value =
org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(
getServletConfig());
}
public void _jspDestroy() {
_jspx_tagPool_c_out_value.release();
}
public void _jspService(HttpServletRequest request, HttpServletResponse
response) throws java.io.IOException, ServletException {
JspFactory _jspxFactory = null;
PageContext pageContext = null;
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
try {
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=GB2312");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("/r/n");
out.write("/r/n/r/n");
out.write("/r/n");
out.write("/r/n ");
out.write("CH3 - HelloJSP.jsp");
out.write("/r/n");
out.write("/r/n");
out.write("/r/n/r/n");
out.write("JSP 将会被转译为 Servlet");
out.write("
/r/n/r/n");
out.write("/r/n");
if (_jspx_meth_c_out_0(pageContext))
return;
out.write("/r/n");
String name = "browser";
out.println("大家好 !!");
out.write("/r/n");
out.print( name );
out.write("/r/n/r/n");
out.write("/r/n");
out.write("");
} catch (Throwable t) {
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (pageContext != null) pageContext.handlePageException(t);
}
} finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
}
}
private boolean _jspx_meth_c_out_0(PageContext pageContext)
throws Throwable {
JspWriter out = pageContext.getOut();
// c:out
org.apache.taglibs.standard.tag.rt.core.OutTag _jspx_th_c_out_0 =
(org.apache.taglibs.standard.tag.rt.core.OutTag) _jspx_tagPool_c_out_value.
get( org.apache.taglibs.standard.tag.rt.core.OutTag.class);
_jspx_th_c_out_0.setPageContext(pageContext);
_jspx_th_c_out_0.setParent(null);
_jspx_th_c_out_0.setValue(new String("Hi"));
int _jspx_eval_c_out_0 = _jspx_th_c_out_0.doStartTag();
if (_jspx_th_c_out_0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE)
return true;
_jspx_tagPool_c_out_value.reuse(_jspx_th_c_out_0);
return false;
}
}
当JSP 被转译成Servlet 时,内容主要包含三部分:
public void _jspInit() {
…. 略
}
public void _jspDestroy() {
…. 略
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
}
public void _jspService(HttpServletRequest request, HttpServletResponse
response) throws java.io.IOException, ServletException {
…. 略
}
_jspInit( ):当JSP 网页一开始执行时,最先执行此方法。因此,我们通常会把初始化的工作写在
此方法中。
_jspDestroy( ):JSP 网页最后执行的方法。
_jspService( ):JSP 网页最主要的程序都是在此方法中。
接下来笔者将HelloJSP.jsp 和HelloJSP_jsp.java 做一个简单的对照:
<%@ page contentType="text/html;charset=GB2312" %>
response.setContentType("text/html;charset=GB2312");
<%! int k = 0; %>
int k = 0; // 此为全局变量
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
CH3 - HelloJSP.jsp
JSP 将会被转译为 Servlet
out.write("/r/n");
out.write("/r/n/r/n");
out.write("/r/n");
out.write("/r/n ");
out.write("CH3 - HelloJSP.jsp");
out.write("/r/n");
out.write("/r/n");
out.write("/r/n/r/n");
out.write("JSP 将会被转译为 Servlet");
out.write("
/r/n/r/n");
out.write("/r/n");
<%@ taglib prefix="c" uri=" http://java.sun.com/jsp/jstl/core" %>
if (_jspx_meth_c_out_0(pageContext))
return;
…. 略
private boolean _jspx_meth_c_out_0(PageContext pageContext)
throws Throwable {
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
JspWriter out = pageContext.getOut();
// c:out
org.apache.taglibs.standard.tag.rt.core.OutTag _jspx_th_c_out_0 =
(org.apache.taglibs.standard.tag.rt.core.OutTag) _jspx_tagPool_c_out_value.
get(org.apache.taglibs.standard.tag.rt.core.OutTag.class);
_jspx_th_c_out_0.setPageContext(pageContext);
_jspx_th_c_out_0.setParent(null);
_jspx_th_c_out_0.setValue(new String("Hi"));
int _jspx_eval_c_out_0 = _jspx_th_c_out_0.doStartTag();
if (_jspx_th_c_out_0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE)
return true;
_jspx_tagPool_c_out_value.reuse(_jspx_th_c_out_0);
return false;
}
<%
String name = "browser";
out.println("大家好 !!");
%>
<%= name %>
String name = "browser";
out.println("大家好 !!");
out.write("/r/n");
out.print( name );
3-5 JSP 与ASP 和ASP+的比较
JSP 与ASP 的比较
一般说来,Sun 公司的JavaServer Pages(JSP)和Microsoft 的Active Server Pages(ASP)
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
在技术方面有许多相似之处。两者都为动态网页的技术,并且双方都能够替代CGI 技术,使网站的
开发时程能够大大缩短,在性能上也有较高的表现,更重要的一点是,两者都能够为程序员提供组
件设计的功能,通过组件设计,将网页中逻辑处理部分交由组件负责处理(ASP 使用COM 组件、JSP
则有JavaBean 组件),而和网页上的排版、美工分离。
尽管JavaServer Pages 技术和Active Server Pages(ASP)在许多方面都很相似,但仍然存
在很多不同之处,其中本质上的区别在于:两者是来源于不同的技术规范组织。以下就来比较两大
技术有哪些不同点,而又为各自带来哪些优势。
平台和服务器的弹性
ASP (Active Server Pages)技术主要在微软(Microsoft)公司的Windows 平台上运行,其中包括
Windows 2000、Windows XP 和Windows 2003,并且搭配其WEB 服务器IIS (Internet Information
Services)。但是,在其他的平台运行时,不是性能低落,就是根本不支持,因此,当在开发网站系
统时,选择NT+IIS+ASP的体系结构时,未来当系统无法负荷时,也只能继续选择Windows 平台的
服务器,无法改写在性能表现相当优异的UNIX 平台上。
JSP (JavaServer Pages)技术主要运行在操作系统上的一个Java Virtual Machine (JVM)虚拟机器上,
因此,它能够跨越所有的平台,例如:NT、Windows 2000、Solaris、Linux、OS/390、AIX、HP-UX ,
等等,除了能在各式各样的操作系统上执行,并且能搭配现有的WEB服务器:Apache、IIS、Netscape
Enterprise Server ,等等,将静态的HTML网页交由执行速度较快的Web Server 处理,而动态产生
网页的部分,就交由JSP Container 来执行。由上述可知,JSP (JavaServer Pages)技术在跨平台的表现
比ASP来得更有弹性。
WEB 网页程序员未来在开发电子商务平台时,就不需要再考虑客户厂商的操作系统平台,可更专
心于系统功能的开发。相应地,厂商在使用JavaServer Pages 技术开发的系统平台时,不再需要担
心未来在扩充软、硬件时,是否产生不兼容的问题。光这一点,就能为企业省下一大笔的费用,这
是JSP 的主要优点。
语法结构
ASP语法结构上,是以"<%"和"%>"作为标记符号,而JSP也是使用相同标记符号作为程序的区
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
段范围的。但不同的是,标记符号之间所使用的语言:ASP为JavaScript或VBScript;而JSP为Java。
Java 是有严格规划、强大且易扩充的语言,远优于VBScript语言。
Java 使程序员的工作在其他方面也变得一样容易、简单。例如:当ASP应用程序在Windows NT
系统可能会造成系统Crash (当机)时,由于JSP是在JVM上执行程序,且提供强大的异常事件处理
机制,因此,不会因为程序撰写的疏忽,而导致服务器操作系统的损毁。
并且Java 语言提供防止直接存取内存的功能,存取内存产生的错误,通常也正是造成服务器损
毁的最主要原因之一。最后,最重要的原因,Java语言是一个有严谨规范、有系统组织的语言,对
一个专业的Java 程序员来说,也真正达到 Learn Once,Write Anywhere(学一次,皆可开发)的境
界。
开放的开发环境
自从1995 年,Sun 公司已经开放技术与国际Java 组织合作开发和修改Java 技术与规范。针对
JSP 的新技术,Sun 公司授权工具供货商(如Macromedia)、同盟公司(如Apache、Netscape)、协
力厂商及其他公司。最近,Sun公司将最新版本的Servlet 2.4和JSP 2.0的源代码发放给Apache,以
求JSP与Apache紧密地相互发展。Apache、Sun和许多其他的公司及个人公开成立一个咨询机构,
以便任何公司和个人都能免费取得信息。(详见: http://jakarta.apache.org)
JSP应用程序接口(API)毫无疑问已经取得成功,并随着Java 组织不断扩大其应用的范围,目
前全力发展Java 技术的厂商不胜枚举,例如:最近IBM 公司强力推广的WebSphere 家族,正是完
全支持J2EE 标准而开发。数据库厂商Oracle 也发展自己的Application Server 来和自己公司本身数
据库产品Oracle 9i 做一紧密的结合。那也更不用提Amazon 系统的供货商BEA 公司,它的产品
WebLogic也是完全支持JavaServer Pages技术和J2EE 规范的。
相反,ASP 技术仅依靠微软本身的推动,其发展建立在独占、封闭的基础之上,并且微软本
身的技术又只允许在微软相关平台的服务器上执行,因此,在标准方面显得有点力不从心。
语法的延展性
ASP 和JSP 都使用标签与Scripting Language来制作动态WEB 网页,JavaServer Pages 2.0新
规范中,能够让程序员自由扩展JSP 标签来应用。JSP开发者能自定义标签库( Tag Library ),所
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
以网页制作者能充分利用与XML 兼容的标签技术强大的功能,大大减低对Java语法的依赖,并且也
可以利用XML强大的功能,做到数据、文件格式的标准化。相关标签库请参考“第十五章:JSP Tag
Library”,其中有更加完整的说明。
执行性能表现
ASP 和JSP 在执行性能的表现上,有一段显著的差距,JSP 除了在一开始加载的时间会比较久
外,之后的表现就远远比ASP 的表现来得好。原因在于:JSP 在一开始接受到请求时,会产生一份
Servlet 实体( instance ),它会先被暂存在内存中,我们称之为持续( Persistence ),当再有
相同请求时,这实体会产生一个线程(thread)来服务它。如果过了一段时间都不再用到此实体时,
Container 会自动将其释放,至于时间的长短,通常都是可以在Container 上自行设定的。
而ASP在每次接收到请求时,都必须要重新编译,因此,JSP 的执行比每次都要编译执行的ASP
要快,尤其是程序中存在循环操作时,JSP 的速度要快上1 到2倍。不过,ASP在这部分的缺陷,将
随ASP+的出现有所改观,在新版的ASP+技术中,性能表现上有很大的突破。
JSP 与ASP+的比较
1. [玉玉3]面向对象性
C#为一种面向对象语言,从很多方面来看,C#将给ASP+带来类似于Java 的功能,并且它和
Windows 环境紧密结合,因此,具备更快的性能。笔者认为,C#是微软在市场上击败Java的主要工
具。
2. 数据库连接
ASP 最大的优点是它使用ADO 对象,因此,ASP Web数据库应用开发特别简单。ASP+发展了更多
的功能,因为有了ADO+,ADO+带来了更强大更快速的功能。JSP 和JDBC 目前在易用性和性能上和
ASP/ADO 相比已有些落后,当新版本ASP+/ADO+出现后这样的差别会更明显,这部分希望Sun 尽快追
赶ASP+/ADO+的组合。
3. 大型网站应用
ASP+将对大型网站有更好的支持。事实上,微软在这方面付出了巨大的努力, ASP+可以让你考
虑到多服务器(multiple servers)的场合,当你需要更强大的功能时,仅仅只需要增加一台服务器。
ASP+现在可以在大型项目方面与JSP 一样具有等同的能力,而且ASP+还有价格方面的优势,因为所
有的组件将是服务器操作系统的一部分。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
结论:
除了上述ASP、ASP+和JSP 之外,笔者再提供一篇在网络上ASP 和JSP 比较的文章:
http://www.indiawebdevelopers.com/technology/Java/jsp.asp,希望能带给读者更客观的评论。
除了ASP 之外,PHP 和ColdFusion 皆为近年来常用来开发WEB 动态网页内容的工具,各开发工
具皆有其优、缺点。ASP 和PHP 最大的好处就是开发中、小型网站非常快速,市面上的书籍也较多,
学习起来能较快上手。尤其因为PHP 的环境大都为UNIX的环境,因此,在规划、构建时,所花需的
成本为最低,但PHP 并未将Presentation Layer 和Business Layer 做一个适当的处理,因此,往
往一个系统越来越庞大、越来越复杂时,维护起来就会越来越吃力,并且本身并没有一个强而有力
的技术在支持它,当开发系统要求为分布式的体系结构时,那么PHP 可能就英雄无用武之地了。
3-6 JSP 2.0 新功能
J2EE 1.4 正式发布之后,Servlet 和JSP 同时也做了一些变动,Servlet 从2.3 更新至2.4;而JSP
从1.2 更新至2.0。两者平心而论,JSP的变动较Servlet来得多,其中JSP 2.0较JSP 1.2新增的功能
如下:
(1) Expression Language;
(2) 新增Simple Tag 和Tag File;
(3) web.xml 新增元素。
3-6-1 Expression Language
JSP 2.0 之后,正式将EL 纳入JSP 的标准语法。EL 主要的功用在于简化JSP 的语法,方便Web
开发人员的使用。例如:
使用JSP 传统语法:
<%
String str_count = request.getParameter("count");
int count = Integer.parseInt(str_count);
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
count = count + 5;
out.println("count:" + count);
%>
使用EL 语法:
count:${param.count + 5}
对于EL 的部分,本书的“第六章:Expression Language”有详尽的介绍。
3-6-2 新增Simple Tag 和Tag File
JSP 2.0提供一些较为简单的方法,让开发人员来撰写自定义标签。JSP 2.0提供两种新的机制,
分别为Simple Tag和Tag File。
Simple Tag Handler和其他Tag Handler(如:Body Tag Handler、Tag Handler和Iteration Tag Handler)
不同之处在于:Simple Tag Handler 并无doStartTag( )和doEndTag( ),它只有doTag( ),因此,实现
标签能比以往更为方便。
Tag File 就更为简单,你可以把它当做直接使用JSP 的语法来制作标签。例如:
Hello.tag
<%
out.println("Hello from tag file.");
%>
我们先制作一个名为Hello.tag 的Tag File,然后将它放置在WEB-INF/tags/ 目录下。在JSP
网页使用Hello.tag 的方法如下:
<%@ taglib prefix="myTag" tagdir="/WEB-INF/tags" %>
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
最后执行的结果如下:
Hello from tag file.
有关Simple Tag Handler和Tag File 的部分,在“第十六章:Simple Tag与Tag File”有更
详细的说明。
3-6-3 web.xml 新增元素
元素主要用来设定JSP 相关配置, 包括 和
两个子元素。其中元素在JSP 1.2 时就已经存在;而
是JSP 2.0 新增的元素。
元素主要有八个子元素,它们分别为:
:设定的说明;
:设定名称;
:设定值所影响的范围,如:/CH2 或 /*.jsp;
:若为true,表示不支持EL 语法;
:若为true,表示不支持<% scripting %>语法;
:设定JSP 网页的编码;
:设置JSP 网页的抬头,扩展名为.jspf;
:设置JSP 网页的结尾,扩展名为.jspf。
图3-3所示的所谓JSP网页的抬头为网页最上方的This banner included with ;
结尾为网页最下方的This banner included with 。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图3-3 Tomcat 上的范例程序
其中抬头的源程序为:
prelude.jspf
This banner included with <include-prelude>
结尾的源程序为:
coda.jspf
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
This banner included with <include-coda>
下面是一个简单的元素完整配置:
Taglib
/WEB-INF/tlds/MyTaglib.tld
Special property group for JSP Configuration JSP example.
JSPConfiguration
/jsp/*
true
GB2312
true
/include/prelude.jspf
/include/coda.jspf
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
第四章 JSP 语法
4-1 Elements 和Template Data
JSP 网页主要分为Elements 与Template Data 两部分。
Template Data:JSP Container 不处理的部分,例如:HTML 的内容,会直接送到Client 端执
行。
Elements:必须经由JSP Container 处理的部分,而大部分Elements 都以XML 作为语法基础,
并且大小写必须要一致。
Elements 有两种表达式,第一种为起始标签(包含Element 名称、属性),中间为一些内容,最
后为结尾标签。如下所示:
body
另一种是标签中只有Element 的名称、属性,称为Empty Elements。如下所示:
Elements 有四种类型:Directive Elements、Scripting Elements、Action Elements 和EL
Elements,接下来的章节会针对前三种类型的Elements加以说明。至于EL Elements是JSP 2.0新
增的功能,笔者将在“第六章:Expression Language”中详细介绍它。
4-2 批注 (Comments)
一般批注可分为两种:一种为在客户端显示的批注;另外一种就是客户端看不到,只给开发程
序员专用的批注。
● 客户端可以看到的批注:
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
例如:
在客户端的HTML 源文件中显示为:
这种批注的方式和HTML 中很像,它可以使用“查看源代码”来看到这些程序代码,但是惟一有
些不同的是,你可以在批注中加上动态的表达式(如上例所示)。
● 开发程序员专用的批注:
<%-- comment --%>
或者
<% /** this is a comment **/ %>
接下来看下面这个范例:
<%@ page language="java" %>
A Comment Test
A Test of Comments
<%-- 这个批注不会显示在客户端 --%>
从用户的浏览器中,看到的源代码如下:
A Comment Test
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
A Test of Comments
之前加上去的批注在客户端的浏览器上看不出来,并且用此批注的方式,在JSP 编译时会被忽
略掉。这对隐藏或批注JSP 程序是实用的方法,通常程序员也会利用它来调试(Debug)程序。
JSP Container不会对 <%--和--%>之间的语句进行编译,它不会显示在客户端的浏览器上,也
无法从源文件中看到。接下来介绍Quoting 和Escape 的规则。
4-3 Quoting 和Escape 规则
Quoting 主要是为了避免与语法产生混淆所使用的转换功能,和HTML 的标签语法类似,JSP 是
以<%标签作为程序的起始、%>标签作为程序的结束,所以当你在JSP 程序中要加上 <%或是%>这
些符号时,应该这么做:
Quoting.jsp
<%@ page contentType="text/html;charset=GB2312 " %>
CH4 - Quoting.jsp
Quoting 范例程序
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
<%
out.println("JSP 以%>作为结束符号");
%>
程序执行时,JSP 在执行到 %>时,JSP Container 就直接告诉你程序有错误,如图4-1所示:
图4-1 Quoting.jsp 的执行结果
通常为了避免产生这样的结果,因此程序中遇到显示%>时,要改写为%/>,所以上面的程序代码
应改写为:
Quoting1.jsp
<%@ page contentType="text/html;charset=GB2312" %>
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
CH4 - Quoting1.jsp
Quoting 范例程序 2
<%
out.println("JSP 以%/>作为结束符号");
%>
Quoting1.jsp 的执行结果如图4-2 所示:
图4-2 Quoting1.jsp 的执行结果
除了 %> 要改为 %/>,当遇到<%、'、"、/ 时都要做适当修改,如下所示:
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
单引号 ' 改为 /'
双引号 " 改为 /"
斜线 / 改为 //
起始标签 <% 改为 <%
结束标签 %> 改为 %/>
最后再举个例子,如下:
Quoting2.jsp
<%@ page contentType="text/html;charset=GB2312" %>
CH4 - Quoting2.jsp
Quoting 范例程序 3
<%
out.println("JSP 遇到 /'、/"、//、<%、%/> 时需要做适当的修改");
%>
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
执行的结果如图4-3 所示:
图4-3 Quoting2.jsp 的执行结果
4-4 Directives Elements(1)
指令(Directives)主要用来提供整个JSP 网页相关的信息,并且用来设定JSP网页的相关属性,
例如:网页的编码方式、语法、信息等。
起始符号为: <%@
终止符号为: %>
内文部分就是一些指令和一连串的属性设定,如下所示:
<%@ directive { attribute ="value" } * %>
什么叫做一连串的属性设定?举例来说,当我们设定两个属性时,可以将之合二为一,如下:
<%@ directive attribute1 = "value1" %>
<%@ directive attribute2 = "value2" %>
亦可以写成:
<%@ directive attribute1 = "value1" attribute2 = "value2" %>
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
在JSP 1.2 的规范中,有三种指令:page、include 和taglib,每一种指令都有各自的属性。
接下来,我们会依序为各位读者介绍这三种指令。
JSP 2.0 新增Tag File 的功能,Tag File 是以 .tag 作为扩展名的。在Tag File 中,因为它
并不是JSP 网页,所以不能使用page 指令,但是它可以使用include 和taglib 指令。除此之外,
Tag File 还有自己本身的指令可以使用,如:tag、attribute 和variable。
有关Tag File 的指令,笔者在“第十六章:Simple Tag 与Tag File”中再做详细介绍,本章
先暂时不谈论它。
4-4-1 page 指令
page 指令是最复杂的JSP指令,它的主要功能为设定整个JSP 网页的属性和相关功能。page 指
令的基本语法如下:
<%@ page attribute1="value1" attribute2= "value2" attribute3=…%>
page 指令是以<%@ page 起始,以%>结束。像所有JSP 标签元素一样,page 指令也支持以XML
为基础的语法,如下所示:
page 指令有11 个属性,如表4-1 所示:
表4-1
属 性 定 义
language =
"scriptingLanguage"
主要指定JSP Container要用什么语言来编译JSP 网页。
JSP 2.0 规范中指出,目前只可以使用Java语言,不过未
来不排除增加其他语言,如C、C++、Perl 等等。默认值
为Java
extends = "className" 主要定义此JSP 网页产生的Servlet 是继承哪个父类
import = "importList" 主要定义此JSP 网页可以使用哪些Java API
session = "true | false" 决定此JSP 网页是否可以使用session 对象。默认值为
true
buffer = "none | size in
kb"
决定输出流 (output stream)是否有缓冲区。默认值为
8KB 的缓冲区
autoFlush = "true |
false"
决定输出流的缓冲区是否要自动清除,缓冲区满了会产生
异常 (Exception)。默认值为 true
isThreadSafe = "true | 主要是告诉JSP Container,此JSP 网页能处理超过一个
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
false" 以上的请求。默认值为 true,如果此值设为 false,
SingleThreadModel 将会被使用。SingleThreadModel 在
Servlet 2.4 中已经声明不赞成使用(deprecate)
info = "text" 主要表示此JSP 网页的相关信息
errorPage = "error_url" 表示如果发生异常错误时,网页会被重新指向那一个URL
isErrorPage = "true |
false"
表示此JSP Page 是否为处理异常错误的网页
contentType = "ctinfo" 表示MIME 类型和JSP 网页的编码方式
pageEncoding = "ctinfo" 表示JSP 网页的编码方式
isELIgnored = "true |
false"
表示是否在此JSP 网页中执行或忽略EL 表达式。如果为
true 时,JSP Container将忽略EL表达式;反之为false
时,EL 表达式将会被执行
下面的范例都合乎语法规则:
<%@ page info = "this is a jsp page"%>
<%@ page language = "java" import = "java.net.* " %>
<%@ page import = "java.net.*,java.util.List " %>
下面的范例也是page 指令,不过并不合乎语法规则,因为session 属性重复设定两次:
<%@ page language = "java" import = "java.net.* " session = "false" buffer = "16kb"
autoFlush = "false" session = "false" %>
注意:只有import 这个属性可以重复设定,其他则否。
<%@ page import = "java.net.* " %>
<%@ page import = "java.util.List " %>
另外再举个较常见的错误例子:
<%@ page language="java" contentType="text/html";charset ="Big5" %>
应该改为:
<%@ page language="java" contentType="text/html;charset=Big5" %>
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
通常我们都以为只要把charset 设为Big5的编码方式,就能够顺利显示出所需要的中文,不过
有时候在显示一些特别的中文字时,例如:碁,会变成乱码。如下范例:
Big5.jsp
<%@ page contentType="text/html;charset=Big5" %>
CH4 - Big5.jsp
使用 Big5 編碼,無法正確顯示某些中文字
<%
out.println("宏?砦q 脑公司");
%>
Big5.jsp 的执行结果如图4-4 所示:
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图4-4 Big5.jsp 的执行结果
那么我们应该如何解决这个问题?很简单,只要把之前的charset = Big5 改为charset = MS950
的编码方式就能够解决这个问题,我们看下面这个范例:MS950.jsp。
MS950.jsp
<%@ page contentType="text/html;charset=MS950" %>
CH4 - MS950.jsp
使用 MS950 編碼,能正確顯示"碁"
<%
out.println("宏碁電腦公司");
%>
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
MS950.jsp 的执行结果如图4-5:
图4-5 MS950.jsp 的执行结果
使用最基本的page 指令的范例程序 (二):Date.jsp
Date.jsp
<%@ page contentType="text/html;charset=GB2312 " %>
<%@ page import="java.util.Date" %>
CH4 - Date.jsp
使用 java.util.Date 显示目前时间
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
<%
Date date = new Date();
out.println("现在时间:"+date);
%>
因为Date.jsp 要显示出现在的时间,所以要先导入(import) java.util 这个套件,才可以使
用Date( )类。执行结果如图4-6 所示:
图4-6 Date.jsp 的执行结果
如果在一个JSP 网页同时须要导入很多套件时:
<%@ page import="java.util.Date" %>
<%@ page import="java.text.*" %>
亦可以写为:
<%@ page import="java.util.Date, java.text.*" %>
直接使用逗号“,”分开,然后就可以一直串接下去。
4-4-2 include 指令
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
include 指令表示:在JSP 编译时插入一个包含文本或代码的文件,这个包含的过程是静态的,
而包含的文件可以是JSP 网页、HTML 网页、文本文件,或是一段Java 程序。
注意
包含文件中要避免使用、、、,因为这将会影响在原来JSP 网
页中同样的标签,这样做有时会导致错误。
include 指令的语法如下:
<%@ include file = "relativeURLspec" %>
include 指令只有一个属性,那就是file,而relativeURLspec 表示此file 的路径。像所有
JSP 标签元素一样,include 指令也支持以XML 为基础的语法,如下所示:
注意
<%@ include %>指令是静态包含其他的文件。所谓的静态是指file 不能为一变量URL,例
如:
<% String URL="JSP.html" ; %>
<%@ include file = "<%= URL %>" %>
也不可以在file 所指定的文件后接任何参数,如下:
<%@ include file = "javaworld.jsp?name=browser" %>
同时,file 所指的路径必须是相对于此JSP 网页的路径。
笔者写了一个Include.jsp范例程序,它include一份HTML的网页,网页文件名叫做Hello.html,
看看执行之后,会有什么结果产生。
Include.jsp
<%@ page contentType="text/html;charset=GB2312" %>
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
CH4 - Include_Html.jsp
include 指令
<%@ include file="Hello.html" %>
<%
out.println("欢迎大家进入JSP 的世界");
%>
Hello.html
JSP 2.0 Tech Reference
执行结果如图4-7。
注意
Hello.html 网页内容中有中文时,Tomcat 5.0.16 执行Include.jsp 时,无法正确显示
Hello.html 网页的中文,会产生乱码。但是笔者使用Resin 来执行时,却可以顺利显示中
文。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
图4-7 Include.jsp 的执行结果
4-4-3 taglib 指令
taglib 指令是JSP 1.1新增进来的功能,能够让用户自定义新的标签。这里只是先做一个简单
介绍,在第十五章再为各位读者详细介绍。
taglib 指令的语法如下:
<%@ taglib uri = "tagLibraryURI" prefix="tagPrefix" %>
像所有JSP标签元素一样,taglib指令也支持以XML为基础的语法,如下所示(见表4-2):
表4-2
属 性 定 义
uri = "tagLibraryURI" 主要是说明taglibrary 的存放位置
prefix="tagPrefix" 主要用来区分多个自定义标签
范例:
<%@ taglib uri ="/supertags/" prefix="super" %>
……….
……..
……..
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
4-5 Scripting Elements
Scripting Elements 包含三部分:
1. 声明(Declarations)
2. Scriptlets
3. 表达式 (Expressions)
示例:
<%! 这是声明 %>
<% 这是Scriptlets %>
<%= 这是表达式 %>
4-5-1 声明 (Declarations)
在JSP 程序中声明合法的变量和方法。声明是以<%! 为起始;%> 为结尾。
声明的语法:
<%! declaration; [ declaration; ]+ ... %>
范例:
<%! int i = 0; %>
<%! int a, b, c; %>
<%! Circle a = new Circle(2.0); %>
<%! public String f(int i) {if ( i < 3 ) return ("i 小于3")}; %>
使用<%! %>可以声明你在JSP 程序中要用的变量和方法,你可以一次声明多个变量和方法,只
要最后以分号“;”结尾就行,当然这些声明在Java 中要是合法的。
每一个声明仅在一个页面中有效,如果你想每个页面都用到一些声明,最好把它们写成一个单
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
独的JSP 网页,然后用<%@ include %>或元素包含进来。
注意
使用<%! %>方式所声明的变量为全局变量,即表示:若同时n 个用户在执行此JSP网页时,
将会共享此变量。因此笔者强烈建议读者,千万别使用<%! %>来声明您的变量。
若要声明变量时,请直接在<% %>之中声明使用即可。
4-5-2 Scriptlets
Scriptlet 中可以包含有效的程序片段,只要是合乎Java 本身的标准语法即可。通常我们主要
的程序也是写在这里面,Scriptlet 是以 <% 为起始;%> 为结尾。
Scriptlet 的语法:
<% code fragment %>
范例:
<%
String name = null;
if (request.getParameter("name") == null) {
%>
………
………
<%
}
else
{
out.println("HI … "+name);
}
%>
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
Scriptlet 能够包含多个语句,方法,变量,表达式,因此它能做以下的事:
(1) 声明将要用到的变量或方法;
(2) 显示出表达式;
(3) 使用任何隐含的对象和使用声明过的对象,编写JSP 语句 (如果你在使用
Java 语言,这些语句必须遵从Java Language Specification);
(4) 当JSP收到客户端的请求时,Scriptlet 就会被执行,如同Servlet的doGet()、doPost(),
如果Scriptlet 有显示的内容会被存在out 对象中,然后再利用out 对象中的println()方法显示
出结果。
4-5-3 表达式 (Expressions)
Expressions 标签是以 <%= 为起始;%> 为结尾,其中间内容包含一段合法的表达式,例如:
使用Java 的表达式。
Expressions 的语法:
<%= expression %>
范例:
<%= getName() %>
<%= (new java.util.Date()).toLocaleString() %>
表达式在执行后会被自动转化为字符串,然后显示出来。
当你在JSP 中使用表达式时请记住以下几点:
1. 不能使用分号“;”来作为表达式的结束符号,如下:
<%= (new java.util.Date()).toLocaleString(); %>
但是同样的表达式用在Scriptlet 中就需要以分号来结尾了。
2.这个表达式元素能够包括任何Java 语法,有时候也能作为其他JSP 元素的属性值。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
第四章 JSP 语法
4-6 Action Elements
JSP 2.0 规范中定义一些标准action 的类型,JSP Container 在实现时,也完全遵照这个规范
而制定。Action 元素的语法以XML 为基础,所以,在使用时大小写是有差别的,例如:
和是有所差别的,因此在撰写程序时,必须要特别注意。
目前JSP 2.0 规范中,主要有20 项Action 元素:
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
笔者将这20 个action 元素分为五类:
第一类有3个action元素,它们都用来存取JavaBean,因此这部分将在“第八章:JSP与JavaBean”
详细地介绍。
第二类有6 个action 元素,这部分是JSP 1.2 原有的action 元素,接下来将会介绍它们。
第三类有6 个action 元素,它们主要用在JSP Document 之中。其中是JSP 2.0
新增的元素。
第四类有3 个action 元素,它们主要用来动态产生XML 元素标签的值,这3 个都是在JSP 2.0
中加入进来的元素。
第五类有2 个action 元素,它们主要用在Tag File 中,这部分将在“第十六章:Simple Tag
与Tag File”再来介绍。
补充
JSP Document:使用XML 语法所写成的JSP 网页。例如:
String name="Mike";
Hi !name
4-6-1
元素允许你包含动态和静态文件,这两种产生的结果是不尽相同的。如果包含进
来的只是静态文件,那么只是把静态文件的内容加到JSP 网页中;如果包含进来的为动态文件,那
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
么这个被包含的文件也会被JSP Container 编译执行。
一般而言,你不能直接从文件名称上来判断一个文件是动态的还是静态的,例如:Hello.jsp 就
有可能只是单纯包含一些信息而已,而不须要执行。但是能够自行判断此文件是动态
的还是静态的,于是能同时处理这两种文件。
的语法:
或
*
说明:
有两个属性:page 和flush。
page:可以代表一个相对路径,即你所要包含进来的文件位置或是经过表达式所运算出的相对路径。
flush:接受的值为boolean,假若为true,缓冲区满时,将会被清空。flush 的默认值为false。
在此需要补充一点:在JSP 1.2 之前,flush 必须设为true。
你还可以用传递一个或多个参数给JSP 网页。
范例:
4-6-2
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
这个标签的定义:将客户端所发出来的请求,从一个JSP 网页转交给另一个JSP
网页。不过有一点要特别注意,标签之后的程序将不能执行。笔者用例子来说明:
<%
out.println("会被执行 !!! ");
%>
<%
out.println("不会执行 !!!");
%>
上面这个范例在执行时,会打印出“会被执行 !!!”,不过随后马上会转入到SayHello.jsp 的
网页中,至于out.println("不会执行 !!! ") 将不会被执行。
的语法:
"} />
或
"} >
*
说明:
如果你加上标签,你就能够向目标文件传送参数和值,不过这些目标文件必须也是
一个能够取得这些请求参数的动态文件,例如:.cgi、.php、.asp 等等。
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
只有一个属性page。page 的值,可以是一个相对路径,即你所要重新导向的网页
位置,亦可以是经过表达式运算出的相对路径。
范例:
或者
4-6-3
用来提供key/value 的信息,它也可以与、和
一起搭配使用。
当在用或者时,被包含的网页或转向后的网页会先看看request
对象里除了原本的参数值之外,有没有再增加新的参数值,如果有增加新的参数值时,则新的参数
值在执行时,有较高的优先权。例如:
一个request 对象有一个参数A = foo;另一个参数A = bar 是在转向时所传递的参数,则网
页中的request 应该会为A = bar,foo。注意:新的参数值有较高的优先权。
的语法:
有两个属性:name 和value。name 的值就是parameter 的名称;而value 的值就
是parameter 的值。
范例:
JSP2.0 技术手册
Java爱好者 http://www.javafan.net制作
4-6-4 、和
用于在浏览器中播放或显示一个对象(通常为Applet 或Bean)。
当JSP 网页被编译后送往浏览器执行时,将会根据浏览器的版本替换成