Java服务器高级编程(二)Java服务器高级编程(二)_作者.pdf
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_05.gif)
《Java服务器高级编程(二)Java服务器高级编程(二)_作者.pdf》由会员分享,可在线阅读,更多相关《Java服务器高级编程(二)Java服务器高级编程(二)_作者.pdf(18页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、下载第2章s e r v l e t简介在本书中我们要使用的一个关键工具就是 Java Servlet API。s e r v l e t站在了Java We b应用开发的最前沿,它为服务器端代码和基于 We b的客户之间通信提供了一条容易的途径,因此,它成为服务器端编程的核心,我们将在本书的许多例子中使用 s e r v l e t。在接下来的几章中,我们将深入研究s e r v l e t的工作方式以及servlet API提供的不同工具,同时,也包括一些我们自己构造的工具。Servlet API提供了一个执行服务的类的通用模型,这是它最基本的定义。实事上,根据它的名字,s e r v l
2、 e t是简单、小巧、专门化的服务器。为了避免s e r v l e t程序员考虑连接网络、获取请求、产生格式正确的响应等问题的细节,这些任务都由s e r v l e t容器(c o n t a i n e r)完成,也称这种容器为s e r v l e t引擎(e n g i n e)。这种容器把由任何协议使用的请求转换成 s e r v l e t能够理解的对象,并给s e r v l e t一个能用来发送响应的对象;容器也用来管理s e r v l e t的生命周期,这也将会在本章中讨论到。servlet API库和s e r v l e t引擎作为Java Servlet Devel
3、opment Kit(J S D K)的一部分,可从如下地址下载:h t t p:/j a v a.s u n.c o m/p r o d u c t s/s e r v l e t/。对于本书中的代码,我们使用 JSDK 2.1版,但因为一些 s e r v l e t容器仅和版本 2.0兼容,我们将试图解释 2.1版带来的变化。要想得到 J S D K的S e r v l e t R u n n e r的更多信息或其他s e r v l e t引擎的详情,请查看本书附录。我们将在本章后面简单解释如何用S u n公司的S e r v l e t R u n n e r测试s e r v l
4、e t。本章主要内容如下:解释s e r v l e t容器所扮演的角色。讨论组成servlet API的基础类和接口。完整地开发一个简单s e r v l e t。讨论与s e r v l e t性能有关的话题。通过构造一个作为S M T P邮件客户的s e r v l e t,来说明表单处理技术以及H T M L的生成。2.1 servlet容器s e r v l e t容器负责处理客户请求、把请求传给 s e r v l e t并把结果返回给客户。对于不同的程序,容器的实际实现也许会有所变化,但容器与 s e r v l e t之间的接口是由servlet API定义好的,这个接口定义了
5、s e r v l e t容器在s e r v l e t上要调用的方法及传递给s e r v l e t的对象类。s e r v l e t的生命周期一般如下:servlet容器创建s e r v l e t的一个实例。容器调用这个实例的i n i t()方法。如果容器对该s e r v l e t有请求,则调用此实例的s e r v i c e()方法。容器在销毁本实例前调用它的d e s t r o y()方法。销毁并标记该实例以供作为垃圾收集。这就是一个 s e r v l e t的生命周期。接口规定了在调用 s e r v i c e()方法前,应首先完成 s e r v l e t
6、的第2章第s e rv l e t简介第第1 3i n i t()方法。同样,在s e r v l e t被销毁之前要先调用d e s t r o y()。一旦请求了一个s e r v l e t,就没有办法阻止s e r v l e t容器执行一个完整的生命周期,尽管这不是最优的,但却是接口所要求的。实际上,s e r v l e t容器有必要在s e r v l e t启动时创建它的一个实例,或者说当 s e r v l e t首次被调用时,并保持这个s e r v l e t实例在内存中,让它对所有的请求进行处理。容器可决定在任何时间把这个实例从内存中移走。例如,s e r v l e
7、t有一段时间没有被调用过,或者是容器正在关闭时,如果上述假设发生了,容器很容易把实例移走;当然,得先调用 d e s t r o y()方法。因此,在典型的模型中,s e r v l e t容器为每个s e r v l e t创建一个单独的实例(尽管没有理由能解释为什么该引擎不创建多个实例)。然而,我们还没有考虑到服务器端编程的更多问题。如果s e r v l e t的s e r v i c e()方法正在运行,而s e r v l e t容器又收到另一个请求时会发生什么情况呢?s e r v l e t容器会等到正在运行的 s e r v i c e()方法完全运行结束后再调用它,或者(你也
8、许会为猜到),它会创建另一个程序执行线程来调用 s e r v i c e()。由于没有什么规定来约束一个线程在某时只能调用s e r v i c e()一次,因此,在写 s e r v l e t时,我们必须保证我们的代码是线程安全的并改进J a v a的s y n c h r o n i z e d命令。事实上,s e r v l e t容器并不会每接到一个请求就创建一个新线程,而是使用一个线程池来动态地将线程分配给到来的请求,但是从 s e r v l e t的观点来看,其效果是完全相同的。因此,我们可以勾画一幅典型的 s e r v l e t容器的工作示意图。图 2-1说明了一个s
9、e r v l e t的装入,它先后服务于两个紧接在一起的请求,然后在服务器关闭时卸载它。图2-1线程线程servlet执行初始化执行服务执行服务执行清除Servlet容器创建线程池实例化servlet调用的方法将请求分配给线程调用service()方法调用service()方法将请求分配给线程阻塞所有后面的请求直到活动线程结束终止线程池调用destroy()方法终止servlet容器关闭HTTP请求1HTTP请求2关闭初始化HTTP响应1HTTP响应2下载我们有必要在这里注意 s e r v l e t容器的某些特性。既然 s e r v l e t容器直接和s e r v l e t通信,
10、因而它们一般应该由纯粹的 J a v a代码编写而成。不幸的是,大多数的 We b服务器都用其他的像 C和C+这类语言写成。因此,像 S u n的Java Web Server和有J S D K支持的S e r v l e t R u n n e r这类1 0 0%纯J a v a代码的We b服务器,都有它们自己的 s e r v l e t容器;其他的像 A p a c h e和微软的I I S这类的We b服务器需要一个独立的 J a v a程序实际运行 s e r v l e t。在这种情况下,就需要用一个插件或模块来处理We b服务器本身与s e r v l e t容器之间的通信。比
11、如,对于 Apache JServ来说,这个通信实际上是由一个特殊的称为A J P v 1.1的I n t e r n e t协议进行处理;根据该协议,We b服务器向s e r v l e t发出请求,s e r v l e t容器把结果传回服务器。在这种情况下,容器和 We b服务器甚至不需要在同一台机器上运行。由于s e r v l e t和We b服务器联系得这么紧,因此,它就可用来大大扩展 We b服务器的功能。它甚至可用来提供最基本的功能:对一个 s e r v l e t来说,让它完成一个标准We b服务器的工作过程是完成有可能的,它能把一个 U R L请求映射为一个 H T M
12、 L文件的路径并返回相应的 H T M L文件。S u n的Java Web Server使用s e r v l e t来完成包括C G I的处理、J S P的执行、H T M L模板及服务器端导入(Server Side Includes,S S I)在内的所有事情。必须明确指出的是,s e r v l e t几乎可用在We b服务器上执行你想执行的任何任务。2.1.1 servlet API前面我们从s e r v l e t的观点来讨论了s e r v l e t,现在将详细描述 s e r v l e t接口。要开发s e r v l e t,首先要获得一个Java Servlet D
13、evelopment Kit(J S D K)的拷贝,该拷贝包括所有用来开发和运行s e r v l e t的类及接口函数,同时还包括一个叫 S e r v l e t R u n n e r的成熟的s e r v l e t容器。类和接口组成了两个J a v a包:J a v a x.S e r v l e t和J a v a x.s e r v l e t.h t t p,前者提供我们前面讨论过的基本接口,后者则提供从处理H T T P请求的特殊工具的一般s e r v l e t接口中派生出来的类。1.servlet接口public interface Servlet如前面所讨论的那样,
14、S e r v l e t生命周期由j a v a x.s e r v l e t.s e r v l e t接口定义。当你在写s e r v l e t时,必须直接或间接地实现这个接口。你可能会趋向于间接实现:通过扩展j a v a x.s e r v l e t.G e n e r i c S e r v l e t或者j a v a x.s e r v l e t.h t t p.H t t p S e r v l e t类。在实现s e r v l e t接口时,必须实现以下5个方法:(1)init()方法public void init(ServletConfig config)th
15、rows ServletException一旦对s e r v l e t进行实例化后,s e r v l e t容器就调用i n i t()方法。容器会把一个S e r v l e t C o n f i g类型的对象传递给i n i t()方法,这样s e r v l e t的实例就可把与引擎相关的配置数据保存起来供以后使用。如果 i n i t()方法没有正常结束的话,i n i t()方法会抛出一个 S e r v l e t E x c e p t i o n。一旦抛出S e r v l e t E x c e p t i o n,s e r v l e t就不会再执行,而随后对它的
16、调用会导致容器对它重新装入,并再次运行I n i t()方法。接口规定对任何 s e r v l e t的实例,i n i t()方法只能被调用一次,在任何请求传给s e r v l e t之前,i n i t()方法可在不抛出S e r v l e t E x c e p t i o n的情况运行完毕。(2)service()方法14第第J a v a服务器高级编程下载public void service(ServletRequest req,ServletResponse res)throwsS e r v l e t E x c e p t i o n,I O E x c e p t
17、i o n只有在成功地初始化 s e r v l e t以后,才能调用s e r v i c e()方法来处理用户请求。s e r v i c e()方法有两个参数:S e r v l e t R e q u e s t和S e r v l e t R e s p o n s e对象,请求对象S e r v l e t R e q u e s t提供了访问初始请求数据的方法和字段,响应对象S e r v l e t R e s p o n s e提供了s e r v l e t构造响应的方法。(3)destroy()方法public void destroy()在任何时候都必须考虑到,s e
18、r v l e t容器可以决定中止s e r v l e t服务。在内存不够或We b服务器关闭时都会发生这种情况。在 s e r v l e t容器调用此方法之前,必须给 s e r v i c e()线程足够长的时间来结束执行(也许需要很长一段时间),因此,接口规定了当 s e r v i c e()正在运行时d e s t r o y()将不会被执行。(4)getServletConfig()方法public ServletConfig getServletConfig()我们已经知道,在 s e r v l e t初始化时,s e r v l e t引擎传递进来一个 S e r v l
19、 e t C o n f i g对象并保存在s e r v l e t的实例中。S e r v l e t C o n f i g对象允许访问两项内容:初始化参数和 S e r v l e t C o n t e x t对象。初始化参数通常由 s e r v l e t容器在文件中指定,允许在运行时向s e r v l e t传递有关调度信息;S e r v l e t C o n t e x t对象为s e r v l e t提供了关于 s e r v l e t容器的信息,这一点将在第 5章中进行讨论。g e t S e r v l e t C o n f i g()方法可以让s e r
20、v l e t在任何时间获得该对象及其配置信息。(5)getServletInfo()方法public String getServletInfo()本方法会返回一个S t r i n g对象,该对象包含s e r v l e t的信息(如开发者、创建日期、描述信息等等)。该方法也可用于 s e r v l e t容器。例如,s e r v l e t容器可以显示一张具有描述信息的 s e r v l e t列表。2.GenericServlet类public abstract class GenericServlet implements Servlet,ServletConfig,Seri
21、alizableG e n e r i c S e r v l e t类提供了s e r v l e t接口的基本实现部分。你可能注意到这个类被声明为 a b s t r a c t,这是因为 s e r v i c e()方法声明为 a b s t r a c t,也就意味着如果你要扩展这个类,你必须自己实现s e r v i c e()方法;记住如果一个方法被声明为 a b s t r a c t,则类本身也要声明为 a b s t r a c t。其他生存周期的方法实现如下:i n i t(ServletConfig conf)方法把s e r v l e t C o n f i g对象
22、存储在一个private transient(私有临时的)实例变量(叫c o n f i g)中,g e t S e r v l e t C o n f i g()方法返回指向本对象的指针。当然,这意味着如果你不小心重载此方法,你就不能使用 g e t S e r v l e t C o n f i g()来获得S e r v l e t C o n f i g对象。正因如此,如果你确实想重载的话,一定记着包含对 s u p e r.c o n f i g(c o n f)的调用。为解决这个问题,2.1版的A P I为G e n e r i c S e r v l e t类提供了一个重载的没有
23、参数的 i n i t()方法。现在,在i n i t(S e r v l e t C o n f i g)方法结束时,有一个对 i n i t()的调用,它在目前的G e n e r i c S e r v l e t中是空的。通过重载i n i t(),我们就能包含初始化代码而不必担心调用 s u p e r.i n i t(c o n f)。2.1版的A P I里有一些新东西就是G e n e r i c S e r v l e t类实现了S e r v l e t C o n f i g接口,这使得s e r v l e t开第2章第s e rv l e t简介第第1 5下载16第第J
24、 a v a服务器高级编程下载发者在不用获得 S e r v l e t C o n f i g对象情况下直接调用ServletConfig 方法,这些方法是g e t I n i t P a r a m e t e r()、g e t I n i t P a r a m e t e r N a m e s()和g e t S e r v l e t C o n t e x t(),每种方法只需简单地调用和已存储的s e r v l e t C o n f i g对象相关的方法。G e n e r i c S e r v l e t类包含两个写s e r v l e t日志的方法,它们实际上调
25、用的是 s e r v l e t C o n t e x t上对应的方法。第一个方法log(String msg)将s e r v l e t的名称和m s g参数值写到s e r v l e t容器的日志中,另一个方法log(String msg,Throwable cause)除了包含s e r v l e t名字和报文外还包含一个异常。要了解S e r v l e t C o n t e x t的l o g方法更多的信息,请参见第5章。下面的类包含在j a v a x.s e r v l e t.h t t p包里。3.HttpServlet类H t t p S e r v l e t
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java 服务器 高级 编程 作者
![提示](https://www.taowenge.com/images/bang_tan.gif)
限制150内