首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

[How Tomcat Works]第2章 一个容易的Servlet容器

2013-10-08 
[How Tomcat Works]第2章 一个简单的Servlet容器HttpServer1类Request类Response类StaticResourceProcesso

[How Tomcat Works]第2章 一个简单的Servlet容器
HttpServer1类Request类Response类StaticResourceProcessor类ServletProcessor1类运行应用第二个应用

    运行应用
总结概述

?? 本章通过两个应用程序,介绍了如何开发你自己的Servlet容器。为了让你容易Servlet容器的工作原理,第一个应用程序被设计地尽可能简单,然后演化为稍微复杂一些的第二个Servlet容器。

??? 提示:每章的Servlet容器都是在前一章的基础上逐步演化的,到第17章就变成了一个羽翼丰满(full-functional)的Tomcat Servlet容器。

??? 本章的两个Servlet容器,既能够运行简单的Servlet,也能够处理静态资源。你可以使用PrimitiveServlet来测试本章的Servlet容器。PrimitiveServlet类的代码在Listing 2.1中,源代码文件在webroot目录下。本章的Servlet容器还不能运行更加复杂的Servlet,不过你在下一章就可以学到如何构建更加成熟的Servlet容器。
Listing 2.1: PrimitiveServlet.java

??????????? ? ? ? ? Figure 2.1: The UML diagram of the first servlet container


??? Constants类包含了被其他类引用的静态常量WEB_ROOT。容器可以提供PrimitiveServlet和静态资源,WEB_ROOT就指定了PrimitiveServlet和静态资源所在的目录。

? ?? HttpServer1对象一直等待HTTP请求,直到接收到shutdown命令位置。你可以用第1章中的方法发送shutdowm命令。

??? 本应用的每个类会在以下各小节中进行讨论。

HttpServer1类

??? 本应用的HttpServer1类,和第1章简单Web服务器中的HttpServer类很类似。不过,HttpServer1类既可以处理静态资源,又可以处理Servlet。要请求一个静态资源,你可以在浏览器地址栏中敲入下面的URL:

?

??? await方法等待HTTP请求,直到接收到shutdown命令为止,这会让你想起第1章的await方法。Listing 2.2中的await方法和第1章的区别在于,Listing 2.2的请求既可以派发到StaticResourceProcessor对象,又可以派发都ServletProcessor对象。如果请求的URI以/servlet/开头,那么就会被派发到ServletProcessor对象。否则,请求将被派发到StaticResourceProcessor对象。注意Listing 2.2中灰色的部分(59行~70行)。

Request类

??? Servlet的service方法从容器接收一个javax.servlet.ServletRequest对象和一个javax.servlet.ServletResponse对象作为参数。这也就是说,对每个HTTP请求,Servlet容器都必须创建一个ServletRequest对象和ServletResponse对象,并将它们传递给处理该请求的Servlet的service方法。
???
??? ex02.pyrmont.Request类代表了传递给Servlet的service方法的请求对象。因此,它必须实现javax.servlet.ServletRequest接口。Request类必须提供ServletRequest接口所有方法的实现。不过,我们想让Reuqest类尽量简单,只实现其中一些方法,在后面章节再实现所有的方法。为了通过编译,你必须提供这些方法的“空”实现。从Listing 2.3可以看出,所有返回值类型为Object的方法都返回null。
Listing 2.3: The Request class

??

??? 在getWriter方法中,PrintWriter构造函数的第二个参数是布尔类型,表明是否启用自动刷新(autoflush)功能。第二个参数如果为true,所有的println调用均会刷新到输出流中。不过,调用print方法是不会刷新的。

??? 因此,如果Servlet的service方法的最后一行恰好调用了print方法,那么print的输出是不会被发送到浏览器的。本节的应用就有这个问题,我们将在下一章修复。

??? Response类仍包括第1章中讨论过的sendStaticResource方法。

StaticResourceProcessor类

??? ex02.pyrmont.StaticResourceProcessor类提供静态资源服务。该类只有一个process方法,代码见Listing 2.5。

Listing 2.5: The StaticResourceProcessor class

????????????????????????? Figure 2.2: Fa?ade classes?

? ? 在第二个应用中,我们增加了两个facade类:RequestFacade和ResponseFacade。RequestFacade实现了ServletRequest接口,并通过接受一个Request对象的构造函数进行实例化,其中Request对象将赋值给一个类型为ServletRequest的成员变量。但是,该成员变量的访问类型是,因此不能在RequestFacade类的外部被访问。我们构造了一个RequestFacade对象传递给service方法,而不是将Request对象向上转型成ServletRequest对象再传递给service方法。Servlet程序员仍可以将ServletRequest对象向下转型回RequestFacade,但是他们只能访问SerlvetRequest接口中的方法。现在,parseUri方法就安全了。

??? Listing 2.7展现了RequestFacade类的部分代码。
Listing 2.7: The RequestFacade class??

 The ServletProcessor2 class is similar to ServletProcessor1, except in the following part of its process method: Servlet servlet = null; RequestFacade requestFacade = new RequestFacade(request); ResponseFacade responseFacade = new ResponseFacade(response); try { servlet = (Servlet) myClass.newInstance(); servlet.service((ServletRequest) requestFacade, (ServletResponse) responseFacade); }

热点排行