欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《深入剖析Tomcat》一2.3 应用程序2

程序员文章站 2022-07-14 10:35:27
...

2.3 应用程序2

应用程序1中有一个严重的问题。在ServletProcessor1类的process()方法中,必须将ex02.pyrmont.Request的实例向上转型为javax.servlet.ServletRequest实例,将ex02.pyrmont.Response实例向上转型为javax.servlet.ServletResponse实例,然后将它们作为参数传递给servlet的service()方法:
《深入剖析Tomcat》一2.3 应用程序2

这是不安全的做法,了解这个servlet容器内部工作原理的servlet程序员可以将ServletRequest实例和ServletResponse实例分别向下转型为ex02.pyrmont.Request实例和ex02.pyrmont.Response实例,就可以调用它们各自的公共方法了。有了Request实例后,就可以调用其parse()方法;而有了Response实例后,就可以调用其sendStaticResource()方法。
不能将parse()方法和sendStaticResource()方法设置为私有方法,因为它们会被其他的类调用,但是这两个方法在servlet中不应该是可用的,所以这个方法不好。一种解决方法是将Request类和Response类都设为默认的访问修饰符,这样就不能从ex02.pyrmont包外对它们进行访问了。但是,这里有一个更完美的方法:使用外观类。UML 关系图如图2-2所示。

《深入剖析Tomcat》一2.3 应用程序2

在第2个应用程序中,添加了两个外观类:RequestFacade和ResponseFacade。RequestFacade类实现servletRequest接口,在其构造函数中需要把它指定的一个Reuqest对象传递给ServletRequest对象引用。ServletRequest接口中每个方法的实现都会调用Request对象的相应方法。但是,ServletRequest对象本身是私有的,无法从类的外部进行访问。相比于将Request对象向上转型为ServletRequest对象,并将其传给service()方法,这里会创建一个RequestFacade对象,再将其传递给service()方法。servlet程序员仍然可以将servletRequest实例向下转型为RequestFacade对象,但它们只能访问ServletRequest接口中提供的方法。现在parse()方法和getUri()方法是安全的了。
代码清单2-7给出了RequestFacade类的定义。
《深入剖析Tomcat》一2.3 应用程序2
《深入剖析Tomcat》一2.3 应用程序2

注意RequestFacade类的构造函数,它接受一个Request对象,但立即将其赋给私有的servletRequest对象引用。还要注意的是,RequestFacade中的每个方法会调用servletRequest对象中相对应的方法来执行。
ResponseFacade类的情况与此相同。
应用程序2*需要使用6个类:
HttpServer2
Request
Response
StaticResourceProcessor
servletProcessor2
Constants
HttpServer2类与HttpServer1类相似,只是在其await()方法中它会使用servletProcessor2类,而不是servletProcessor1类:
《深入剖析Tomcat》一2.3 应用程序2

servletProcessor2类与servletProcessor1类相似,只是在其process()方法的以下部分中有些许不同:
《深入剖析Tomcat》一2.3 应用程序2

运行应用程序
要在Windows平台上运行该程序,可以在工作目录下执行如下命令:

java -classpath ./lib/servlet.jar;./ ex02.pyrmont.HttpServer2

在Linux平台上,需要用冒号分割两个库文件:

java -classpath ./lib/servlet.jar:./ ex02.pyrmont.HttpServer2

可以使用与应用程序1相同的URL来测试,结果是相同的。