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

当前页面: 开发资料首页J2EE 专题Servlet容器工作原理(三)

Servlet容器工作原理(三)

摘要: Servlet容器工作原理(三)
内容:

ServletProcessor1 类
    ServletProcessor1 类用来处理对 servlet 的 HTTP 请求。 它非常简单,只包含了一个 process 方法。 而这个方法接受两个参数: 一个javax.servlet.ServletRequest 实例和一个 avax.servlet.ServletResponse实例。 process 方法也构建了一个 java.net.URLClassLoader 对象并使用它装载 servlet 类文件。 在从类装载器获得的 Class 对象上,process 方法创建一个 servlet 实例并调用它的 service 方法。



 


process 方法


Listing 2.4. ServletProcessor1 类中 process 方法



<table style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>

<tr>
<td style="WORD-WRAP: break-word">

public void process(Request request, Response response) {
&nbsp;&nbsp;&nbsp; String uri&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = request.getUri();
&nbsp;&nbsp;&nbsp; String servletName&nbsp;&nbsp;&nbsp; = uri.substring(uri.lastIndexOf("/") + 1);
&nbsp;&nbsp;&nbsp; URLClassLoader loader = null;


&nbsp;&nbsp;&nbsp; try {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // create a URLClassLoader
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URLStreamHandler streamHandler = null;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL[] urls&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = new URL[1];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File classPath&nbsp;&nbsp;&nbsp; = new File(Constants.WEB_ROOT);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String repository = (new URL("file", null,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; classPath.getCanonicalPath() + File.separator)).toString() ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; urls[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = new URL(null, repository, streamHandler);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loader&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = new URLClassLoader(urls);
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; catch (IOException e) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(e.toString());
&nbsp;&nbsp;&nbsp; }


&nbsp;&nbsp;&nbsp; Class myClass = null;


&nbsp;&nbsp;&nbsp; try {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myClass = loader.loadClass(servletName);
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; catch (Exception e) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(e.toString());
&nbsp;&nbsp;&nbsp; }


&nbsp;&nbsp;&nbsp; Servlet servlet = null;
&nbsp;&nbsp;&nbsp; try {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; servlet = (Servlet) myClass.newInstance();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; servlet.service((ServletRequest) request, (ServletResponse) response);
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; catch (Exception e) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(e.toString());
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; catch (Throwable e) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(e.toString());
&nbsp;&nbsp;&nbsp; }
}

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


process 方法接受两个参数:一个 ServletRequest实例和一个 ServletResponse 实例。 process方法通过调用 getRequestUri 方法从 ServletRequest获取 URI。


String uri = request.getUri();
切记 URI 的格式:


/servlet/servletName
servletName 是 servlet 类的名称。


如果要装载 servlet 类,则需要使用以下代码从 URI 获知 servlet 名称:


String servletName = uri.substring(uri.lastIndexOf("/") + 1);
然后 process 方法装载 servlet。 要做到这些,需要创建一个类装载器,并告诉装载器该类的位置, 该 servlet 容器可以指引类装载器在 Constants.WEB_ROOT 指向的目录中查找。 在工作目录下,WEB_ROOT 指向 webroot/ 目录。


如果要装载一个 servlet,则要使用 java.net.URLClassLoader 类,它是java.lang.ClassLoader 的间接子类。 一旦有了 URLClassLoader 类的实例,就可以使用 loadClass 方法来装载一个 servlet 类。 实例化 URLClassLoader 是很简单的。 该类有三个构建器,最简单的是:


public URLClassLoader(URL[] urls);
urls 是一组指向其位置 java.net.URL 对象, 当装载一个类时它会自动搜索其位置。 任一以 / 结尾的 URL 都被假定为一目录, 否则,就假定其为 .jar 文件,在需要时可以下载并打开。


在一个 servlet 容器内,类装载器查找 servlet 类的位置称为储存库 (repository)。


在所举的应用程序中,类装载器只可在当前工作目录下的 webroot/ 目录查找,所以,首先得创建一组简单的 URL。 URL 类提供了多个构建器,因此有许多的方法来构建一个 URL 对象。 在这个应用程序内,使用了和 TOMCAT 内另外一个类所使用的相同的构建器。 该构建器头部 (signature) 如下:


public URL(URL context, String spec, URLStreamHandler hander)
&nbsp;&nbsp;&nbsp; throws MalformedURLException
可以通过传递给第二个参数一个规范,传递给第一个和第三个参数 null 值来使用这个构建器, 但在些有另外一种可接受三个参数的构建器:


public URL(String protocol, String host, String file)
&nbsp;&nbsp;&nbsp; throws MalformedURLException
因此,如果只写了以下代码,编译器将不知道是使用的哪个构建器:


new URL(null, aString, null);
当然也可以能过告诉编译器第三个参数的类型来避开这个问题,如:


URLStreamHandler streamHandler = null;
new URL(null, aString, streamHandler);
对于第二个参数,可以传递包含储存库 (repository) 的 String 。 以下代码可创建:


String repository = (new URL("file", null,
&nbsp;&nbsp;&nbsp; classPath.getCanonicalPath() + File.separator)).toString();
结合起来,以下是构建正确 URLClassLoader 实例的 process 方法的部分代码:



<table style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>

<tr>
<td style="WORD-WRAP: break-word">

// create a URLClassLoader
URLStreamHandler streamHandler = null;


URL[] urls&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = new URL[1];
File classPath&nbsp;&nbsp;&nbsp; = new File(Constants.WEB_ROOT);
String repository = (new URL("file", null,
&nbsp;&nbsp;&nbsp; classPath.getCanonicalPath() + File.separator)).toString() ;
urls[0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = new URL(null, repository, streamHandler);
loader&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = new URLClassLoader(urls);

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


创建储存库 (repository)的代码摘自org.apache.catalina.startup.ClassLoaderFactory内的createClassLoader 方法,而创建 URL 的代码摘自org.apache.catalina.loader.StandardClassLoader 类内的 addRepository 方法。 但在此阶段您还没有必要去关心这些类。


有了类装载器,您可以使用 loadClass 方法装载 servlet 类:



<table style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>

<tr>
<td style="WORD-WRAP: break-word">

Class myClass = null;
try {
&nbsp;&nbsp;&nbsp; myClass = loader.loadClass(servletName);
}
catch (ClassNotFoundException e) {
&nbsp;&nbsp;&nbsp; System.out.println(e.toString());
}
然后,process方法创建已装载的 servlet类的实例,传递给 javax.servlet.Servlet ,并激活 servlet 的 service 方法:


Servlet servlet = null;
try {
&nbsp;&nbsp;&nbsp; servlet = (Servlet) myClass.newInstance();
&nbsp;&nbsp;&nbsp; servlet.service((ServletRequest) request, (ServletResponse) response);
}
catch (Exception e) {
&nbsp;&nbsp;&nbsp; System.out.println(e.toString());
}
catch (Throwable e) {
&nbsp;&nbsp;&nbsp; System.out.println(e.toString());
}

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



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


javac -d . -classpath ./lib/servlet.jar src/ex02/pyrmont/*.java
如果要在 windows 下运行该应用程序,在工作目录下键入以下命令:


java -classpath ./lib/servlet.jar;./ ex02.pyrmont.HttpServer1
在 linux 环境下,使用冒号来隔开类库:


java -classpath ./lib/servlet.jar:./ ex02.pyrmont.HttpServer1
如果要测试该应用程序,请在 URL 或浏览器地址栏键入以下命令:


http://localhost:8080/index.html
或者是:


http://localhost:8080/servlet/PrimitiveServlet
您将会在浏览器中看到以下文本:


Hello. Roses are red.
注意:您不能看到第二行字符 (Violets are blue),因为只有第一行字符送入到浏览器。 Tomcat 运行工作原理 随后的章节会告诉您怎样来解决这个问题。


&nbsp;


关于翻译作者:



<table style="TABLE-LAYOUT: fixed" cellSpacing=0 borderColorDark=#ffffff cellPadding=4 width="98%" align=center bgColor=#e6e6e6 borderColorLight=#009ace border=1>

<tr>
<td style="WORD-WRAP: break-word">petrel&nbsp;,java&nbsp;爱好者,在深圳从事&nbsp;java&nbsp;和数据库的开发工作,喜爱各项运动!可以通过petrel.zhang@ccjk.com&nbsp;与她联系.也可以点击http://www.matrix.org.cn/user_view.asp?username=petrel查看她的信息.</td></tr></table>

Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd, scwcd

↑返回目录
前一篇: Servlet容器工作原理(四)
后一篇: EJB核心技术及其应用