站内搜索: 请输入搜索关键词

当前页面: 开发资料首页JSP 专题Servlet容器工作原理讲解(四)

Servlet容器工作原理讲解(四)

摘要: Servlet容器工作原理讲解(四)



第一个应用程序里存在一个值得注意的问题。 在ServletProcessor1 类的 process 方法里,上溯 (upcast)ex02.pyrmont.Request 实例到 javax.servlet.ServletRequest,将其作为第一个参数传递给 servlet 的 service 方法。 另上溯(upcast) ex02.pyrmont.Response 实例到 javax.servlet.ServletResponse ,并将其作为第二个参数传递给 servlet 的 service 方法。



<table align="center" border="1" bordercolordark="#FFFFFF" bordercolorlight="black" cellpadding="2" cellspacing="0" width="400">
<tr>
<td bgcolor="e6e6e6" class="code" style="font-size:9pt">

try {

servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) request, (ServletResponse) response);
}

</td>
</tr>
</table>



这样会使安全性能大打折扣。 知道 servlet 容器工作原理的程序员可以将 ServletRequest 和 ServletResponse 实例向下转型 (downcast) 到Request 和 Response ,并调用它们的 public 方法。 Request 实例能调用它的 parse 方法; Request 实例能调用它的 sendStaticResource 方法。


可以将 parse 和 sendStaticResource 方法设为 private,因为在 ex02.pyrmont 里将会从其他类里调用它们。 然而,这两个方法在 servlet 内应该是不可用的。 一个解决方法是:给 Request 和 Response 类一个默认的访问修饰符,以致他们在 ex02.pyrmont 外不能被使用。 但还有一个更好的解决方法: 使用 facade 类。


在第二个应用程序内,添加两个 facade 类:RequestFacade 和 ResponseFacade。 RequestFacade 类实现 ServletRequest 接口,并通过传递 Request 实例来实例化, Request 实例将在 ServletRequest 对象的构建器里被引用 。 ServletRequest 对象本身是 private 类型的,不能在类之外访问。 就构建 RequestFacade 对象,并将其传递给 service 方法,而不上溯 (upcast) Request 对象给 ServletRequest,并将其传递给 service 方法。 servlet 程序员仍旧可以向下转型 (downcast) ServletRequest 到 RequestFacade,但是,只要访问 ServletRequest 接口的可用方法就可以了。 现在,parseUri 就安全了。


Listing 2.5 显示 RequestFacade 类部分代码:


Listing 2.5. RequestFacade 类



<table align="center" border="1" bordercolordark="#FFFFFF" bordercolorlight="black" cellpadding="2" cellspacing="0" width="400">
<tr>
<td bgcolor="e6e6e6" class="code" style="font-size:9pt">
package ex02.pyrmont;


public class RequestFacade implements ServletRequest {
private ServletRequest request = null;

public RequestFacade(Request request) {
this.request = request;
}

/* implementation of the ServletRequest*/
public Object getAttribute(String attribute) {
return request.getAttribute(attribute);
}

public Enumeration getAttributeNames() {
return request.getAttributeNames();
}

...
}

</td>
</tr>
</table>



注意 RequestFacade 构造函数。 它会接受一个 Request 对象,即刻分配给私有的 servletRequest 对象引用。 还要注意,RequestFacade 内的每个方法调用 ServletRequest 对象内相应的方法。


ResponseFacade 类也是如此。


以下是 application 2 所包含的类



<table align="center" border="1" bordercolordark="#FFFFFF" bordercolorlight="black" cellpadding="2" cellspacing="0" width="400">
<tr>
<td bgcolor="e6e6e6" class="code" style="font-size:9pt">
HttpServer2

Request
Response
StaticResourceProcessor
ServletProcessor2
Constants
HttpServer2 类类似于 HttpServer1,
只是它在 await 方法内使用了 ServletProcessor2 而不是ServletProcessor1。
if (request.getUri().startsWith(&quot;/servlet/&quot;)) {
ServletProcessor2 processor = new ServletProcessor2();
processor.process(request, response);
}
else {
...
}
ServletProcessor2 类也类似于 ServletProcessor1,
只是在以下 process 方法的部分代码有点不同:
Servlet servlet = null;
RequestFacade requestFacade = new RequestFacade(request);
ResponseFacade responseFacade = new ResponseFacade(response);

try {
servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) requestFacade,
(ServletResponse) responseFacade);
}

</td>
</tr>
</table>



编译并运行该应用程序


如果要编译该应用程序,在工作目录下键入以下命令:


javac -d . -classpath ./lib/servlet.jar src/ex02/pyrmont/*.java


如果要在 windows 下运行该应用程序,在工作目录下键入以下命令:


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


在linux环境下,使用分号来隔开类库:


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


您可以使用和 application 1 相同的 URL 以收到同样的结果。


总结


本文讨论了简单的能够用于服务静态资源,以及处理如 PrimitiveServlet 一样简单的 servlet 的 servlet 容器。 同时也提供 javax.servlet.Servlet 的背景信息。


【关于作者】


本系列文章由petrel翻译,petrel ,java 爱好者,在深圳从事 java 和数据库的开发工作,喜爱各项运动!也可以点击http://www.matrix.org.cn/user_view.asp?username=petrel查看她的信息.或者通过petrel.zhang@ccjk.com 与她联系.


【原文】:http://www.onjava.com/pub/a/onjava/2003/05/14/java_webserver.html【完】
↑返回目录
前一篇: Servlet容器工作原理讲解(三)
后一篇: 利用iText在JSP中生成PDF报表