Tomcat源码学习(14)How Tomcat works(转)

启动应用程序

    你可以从ex03.pyrmont.startup.Bootstrap类来启动应用程序。这个类在Listing 3.1中给出。
         Listing 3.1: Bootstrap类
package ex03.pyrmont.startup;
import ex03.pyrmont.connector.http.HttpConnector;
public final class Bootstrap {
     public static void main(String[] args) {
         HttpConnector connector = new HttpConnector();
         connector.start();
     }
}
    Bootstrap类中的main方法实例化HttpConnector类并调用它的start方法。HttpConnector类在Listing 3.2给出。
         Listing 3.2: HttpConnector类的start方法
package ex03.pyrmont.connector.http;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpConnector implements Runnable {
     boolean stopped;
     private String scheme = "http";
     public String getScheme() {
         return scheme;
     }
     public void run() {
         ServerSocket serverSocket = null;
         int port = 8080;
         try {
             serverSocket = new
             ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
         }
         catch (IOException e) {
             e.printStackTrace();
             System.exit(1);
         }
         while (!stopped) {
             // Accept the next incoming connection from the server socket
             Socket socket = null;
             try {
                 socket = serverSocket.accept();
            }
             catch (Exception e) {
                 continue;
             }
             // Hand this socket off to an HttpProcessor
             HttpProcessor processor = new HttpProcessor(this);
             processor.process(socket);
         }
     }
     public void start() {
         Thread thread = new Thread(this);
         thread.start ();
     }
}

连接器

    ex03.pyrmont.connector.http.HttpConnector类指代一个连接器,职责是创建一个服务器套接字用来等待前来的HTTP请求。这个类在Listing 3.2中出现。
    HttpConnector类实现了java.lang.Runnable,所以它能被它自己的线程专用。当你启动应用程序,一个HttpConnector的实例被创建,并且它的run方法被执行。
    注意: 你可以通过读"Working with Threads"这篇文章来提醒你自己怎样创建Java线程。
    run方法包括一个while循环,用来做下面的事情:
  • 等待HTTP请求
  • 为每个请求创建个HttpProcessor实例
  • 调用HttpProcessor的process方法
     注意:run方法类似于第2章中HttpServer1类的await方法。
    马上你就会看到HttpConnector类和ex02.pyrmont.HttpServer1类非常相像,除了从 java.net.ServerSocket类的accept方法中获得一个套接字之后,一个HttpProcessor实例会被创建,并且通过传递该套 接字给它的process方法调用。
    注意:HttpConnector类有另一个方法叫getScheme,用来返回一个scheme(HTTP)。
    HttpProcessor类的process方法接受前来的HTTP请求的套接字,会做下面的事情:
1. 创建一个HttpRequest对象。
2. 创建一个HttpResponse对象。
3. 解析HTTP请求的第一行和头部,并放到HttpRequest对象。
4. 解析HttpRequest和HttpResponse对象到一个ServletProcessor或者 StaticResourceProcessor。像第2章里边说的,ServletProcessor调用被请求的servlet的service方 法,而StaticResourceProcessor发送一个静态资源的内容。
    process方法在Listing 3.3给出.
Listing 3.3: HttpProcessor类process方法
public void process(Socket socket) {
     SocketInputStream input = null;
     OutputStream output = null;
     try {
         input = new SocketInputStream(socket.getInputStream(), 2048);
         output = socket.getOutputStream();
         // create HttpRequest object and parse
         request = new HttpRequest(input);
         // create HttpResponse object
         response = new HttpResponse(output);
         response.setRequest(request);
         response.setHeader("Server", "Pyrmont Servlet Container");
         parseRequest(input, output);
         parseHeaders(input);
         //check if this is a request for a servlet or a static resource
         //a request for a servlet begins with "/servlet/"
         if (request.getRequestURI().startsWith("/servlet/")) {
             ServletProcessor processor = new ServletProcessor();
             processor.process(request, response);
         }
         else {
             StaticResourceProcessor processor = new
             StaticResourceProcessor();
             processor.process(request, response);
         }
         // Close the socket
         socket.close();
         // no shutdown for this application
     }
     catch (Exception e) {
         e.printStackTrace ();
     }
}
    process首先获得套接字的输入流和输出流。请注意,在这个方法中,我们适合继承了java.io.InputStream的SocketInputStream类。
SocketInputStream input = null;
OutputStream output = null;
try {
     input = new SocketInputStream(socket.getInputStream(), 2048);
     output = socket.getOutputStream();
    然后,它创建一个HttpRequest实例和一个 instance and an HttpResponse instance and assigns
the HttpRequest to the HttpResponse.
// create HttpRequest object and parse
request = new HttpRequest(input);
// create HttpResponse object
response = new HttpResponse(output);
response.setRequest(request);
    本章应用程序的HttpResponse类要比第2章中的Response类复杂得多。举例来说,你可以通过调用他的setHeader方法来发送头部到一个客户端。
response.setHeader("Server", "Pyrmont Servlet Container");
    接下去,process方法调用HttpProcessor类中的两个私有方法来解析请求。
parseRequest(input, output);
parseHeaders (input);
    然后,它根据请求URI的形式把HttpRequest和HttpResponse对象传给ServletProcessor或者StaticResourceProcessor进行处理。
if (request.getRequestURI().startsWith("/servlet/")) {
     ServletProcessor processor = new ServletProcessor();
     processor.process(request, response);
}
else {
     StaticResourceProcessor processor =
         new StaticResourceProcessor();
     processor.process(request, response);
}
    最后,它关闭套接字。
socket.close();
    也要注意的是,HttpProcessor类使用org.apache.catalina.util.StringManager类来发送错误信息:
protected StringManager sm =
     StringManager.getManager("ex03.pyrmont.connector.http");
    HttpProcessor类中的私有方法--parseRequest,parseHeaders和normalize,是用来帮助填充HttpRequest的。这些方法将会在下节"创建一个HttpRequest对象"中进行讨论。
原文地址:https://www.cnblogs.com/macula7/p/1960623.html