• Tomcat源码学习(11)How Tomcat works(转)


    ServletProcessor1类

        Listing 2.6中的ex02.pyrmont.ServletProcessor1类用于处理servlet的HTTP请求。
             Listing 2.6: ServletProcessor1类
    package ex02.pyrmont;
    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());
             }
         }
    }
        ServletProcessor1类出奇的简单,仅仅由一个方法组成:process。这个方法接受两个参数:一个
    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)
    throws MalformedURLException
        你可以使用这个构造方法,并为第二个参数传递一个说明,为第一个和第三个参数都传递null。不过,这里有另外一个接受三个参数的构造方法:
    public URL(java.lang.String protocol, java.lang.String host,
         java.lang.String file) throws MalformedURLException
        因此,假如你使用下面的代码时,编译器将不会知道你指的是那个构造方法:
    new URL(null, aString, null);
        你可以通过告诉编译器第三个参数的类型来避开这个问题,例如。
    URLStreamHandler streamHandler = null;
    new URL(null, aString, streamHandler);
        你可以使用下面的代码在组成一个包含资源库(servlet类可以被找到的地方)的字符串,并作为第二个参数,
    String repository = (new URL("file", null,
    classPath.getCanonicalPath() + File.separator)).toString() ;
        把所有的片段组合在一起,这就是用来构造适当的URLClassLoader实例的process方法中的一部分:
    // create a URLClassLoader
    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);
        注意: 用来生成资源库的代码是从org.apache.catalina.startup.ClassLoaderFactory的createClassLoader方法来的,而生成URL的代码是从org.apache.catalina.loader.StandardClassLoader的addRepository方法来的。不过,在以下各章之前你不需要担心这些类。
        当有了一个类加载器,你可以使用loadClass方法加载一个servlet:
    Class myClass = null;
    try {
         myClass = loader.loadClass(servletName);
    }
    catch (ClassNotFoundException e) {
         System.out.println(e.toString());
    }
        然后,process方法创建一个servlet类加载器的实例, 把它向下转换(downcast)为javax.servlet.Servlet, 并调用servlet的service方法:
    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章修复这个问题。
  • 相关阅读:
    C++继承与派生的概念、什么是继承和派生
    为什么要用重载(学习笔记)
    C++ 为什么要用覆盖(学习笔记)
    做一个爱分享的人技术牛人博客
    okhttp head()请求
    android 8.0 前台服务问题
    android 配置 kotlin 使用jdk1.8编译
    java 获取apk包的版本号、包路径。权限信息
    vue 自定义input控件 v-model 绑定数据问题
    android ViewModel 列表数据获取条数
  • 原文地址:https://www.cnblogs.com/macula7/p/1960787.html
Copyright © 2020-2023  润新知