ServletProcessor1类
Listing 2.6中的ex02.pyrmont.ServletProcessor1类用于处理servlet的HTTP请求。Listing 2.6: ServletProcessor1类
package ex02.pyrmont;ServletProcessor1类出奇的简单,仅仅由一个方法组成:process。这个方法接受两个参数:一个
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
import java.io.File;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ServletProcessor1 {
public void process(Request request, Response response) {
String uri = request.getUri();
String servletName = uri.substring(uri.lastIndexOf("/") + 1);
URLClassLoader loader = null;
try {
// create a URLClassLoader
URL[] urls = new URL[1];
URLStreamHandler streamHandler = null;
File classPath = new File(Constants.WEB_ROOT);
// the forming of repository is taken from the
// createClassLoader method in
// org.apache.catalina.startup.ClassLoaderFactory
String repository =(new URL("file", null, classPath.getCanonicalPath() +
File.separator)).toString() ;
// the code for forming the URL is taken from
// the addRepository method in
// org.apache.catalina.loader.StandardClassLoader.
urls[0] = new URL(null, repository, streamHandler);
loader = new URLClassLoader(urls);
}
catch (IOException e) {
System.out.println(e.toString() );
}
Class myClass = null;
try {
myClass = loader.loadClass(servletName);
}
catch (ClassNotFoundException e) {
System.out.println(e.toString());
}
Servlet servlet = null;
try {
servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) request,
(ServletResponse) response);
}
catch (Exception e) {
System.out.println(e.toString());
}
catch (Throwable e) {
System.out.println(e.toString());
}
}
}
javax.servlet.ServletRequest实例和一个javax.servlet.ServletResponse实例。该方法从ServletRequest中通过调用getRequestUri方法获得URI:
String uri = request.getUri();请记住URI是以下形式的:
/servlet/servletName在这里servletName是servlet类的名字。
要加载servlet类,我们需要从URI中知道servlet的名称。我们可以使用process方法的下一行来获得servlet的名字:
String servletName = uri.substring(uri.lastIndexOf("/") + 1);接下去,process方法加载servlet。要完成这个,你需要创建一个类加载器并告诉这个类加载器要加载的类的位置。对于这个servlet容器,类加载器直接在Constants指向的目录里边查找。WEB_ROOT就是指向工作目录下面的webroot目录。
注意: 类加载器将在第8章详细讨论。
要加载servlet,你可以使用java.net.URLClassLoader类,它是java.lang.ClassLoader类的一个直接子类。一旦你拥有一个URLClassLoader实例,你使用它的loadClass方法去加载一个servlet类。现在举例说明URLClassLoader类是straightforward直接转发的。这个类有三个构造方法,其中最简单的是:
public URLClassLoader(URL[] urls);这里urls是一个java.net.URL的对象数组,这些对象指向了加载类时候查找的位置。任何以/结尾的URL都假设是一个目录。否则,URL会Otherwise, the URL假定是一个将被下载并在需要的时候打开的JAR文件。
注意:在一个servlet容器里边,一个类加载器可以找到servlet的地方被称为资源库(repository)。
在我们的应用程序里边,类加载器必须查找的地方只有一个,如工作目录下面的webroot目录。因此,我们首先创建一个单个URL组成的数组。URL类提供了一系列的构造方法,所以有很多中构造一个URL对象的方式。对于这个应用程序来说,我们使用Tomcat中的另一个类的相同的构造方法。这个构造方法如下所示。
public URL(URL context, java.lang.String spec, URLStreamHandler hander)你可以使用这个构造方法,并为第二个参数传递一个说明,为第一个和第三个参数都传递null。不过,这里有另外一个接受三个参数的构造方法:
throws MalformedURLException
public URL(java.lang.String protocol, java.lang.String host,因此,假如你使用下面的代码时,编译器将不会知道你指的是那个构造方法:
java.lang.String file) throws MalformedURLException
new URL(null, aString, null);你可以通过告诉编译器第三个参数的类型来避开这个问题,例如。
URLStreamHandler streamHandler = null;你可以使用下面的代码在组成一个包含资源库(servlet类可以被找到的地方)的字符串,并作为第二个参数,
new URL(null, aString, streamHandler);
String repository = (new URL("file", null,把所有的片段组合在一起,这就是用来构造适当的URLClassLoader实例的process方法中的一部分:
classPath.getCanonicalPath() + File.separator)).toString() ;
// create a URLClassLoader注意: 用来生成资源库的代码是从org.apache.catalina.startup.ClassLoaderFactory的createClassLoader方法来的,而生成URL的代码是从org.apache.catalina.loader.StandardClassLoader的addRepository方法来的。不过,在以下各章之前你不需要担心这些类。
URL[] urls = new URL[1];
URLStreamHandler streamHandler = null;
File classPath = new File(Constants.WEB_ROOT);
String repository = (new URL("file", null,
classPath.getCanonicalPath() + File.separator)).toString() ;
urls[0] = new URL(null, repository, streamHandler);
loader = new URLClassLoader(urls);
当有了一个类加载器,你可以使用loadClass方法加载一个servlet:
Class myClass = null;然后,process方法创建一个servlet类加载器的实例, 把它向下转换(downcast)为javax.servlet.Servlet, 并调用servlet的service方法:
try {
myClass = loader.loadClass(servletName);
}
catch (ClassNotFoundException e) {
System.out.println(e.toString());
}
Servlet servlet = null;
try {
servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) request,(ServletResponse) response);
}
catch (Exception e) {
System.out.println(e.toString());
}
catch (Throwable e) {
System.out.println(e.toString());
}
运行应用程序
要在Windows上运行该应用程序,在工作目录下面敲入以下命令:java -classpath ./lib/servlet.jar;./ ex02.pyrmont.HttpServer1在Linux下,你使用一个冒号来分隔两个库:
java -classpath ./lib/servlet.jar:./ ex02.pyrmont.HttpServer1要测试该应用程序,在浏览器的地址栏或者网址框中敲入:
http://localhost:8080/index.html或者
http://localhost:8080/servlet/PrimitiveServlet当调用PrimitiveServlet的时候,你将会在你的浏览器看到下面的文本:
Hello. Roses are red.请注意,因为只是第一个字符串被刷新到浏览器,所以你不能看到第二个字符串Violets are blue。我们将在第3章修复这个问题。