《How Tomcat Works》第三章:连接器

前面第二章讲的是简单的servlet容器,其中HttpServer类负责等待Http请求,然后构建解析request,response,之后再通过ClassLoader调用servlet的service方法或者说直接调用静态资源。

到了第三章,就将上一章中的HttpServer类中的等待接受Http请求与解析request,response两大职责拆分了开来,前者成为了HttpConnector,负责构建serverSocket接受请求,后者成为了HttpProcessor,负责解析request与response。
下面这张UML图描述了这些类的关系:
这里写图片描述
下面说一下程序执行的流程:

HttpConnector connector = new HttpConnector();
    connector.start();

首先BootStrap类启动HttpConnector.

public void run() {
    ServerSocket serverSocket = null;
    int port = 8080;
    try {
      serverSocket =  new ServerSocket(port, 1, InetAddress.getByName("127.0.0.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);
    }
  }

然后构建serverSocket ,进入循环之中等待Htttp请求的到来,获取socket之后,调用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();
        }
    }

到了这个方法之后,就创建HttpRequest,HttpRespnse实例,解析请求,解析头部最后再根据uri决定是调用静态资源的process方法,还是调用servlet的service方法。

其实Http请求解析是相当复杂的任务,这里总结一下书上的具体流程:

  1. 获取套接字输入流
  2. 解析请求行(一般是为了获取uri)
  3. 解析头部
  4. 解析cookies
  5. 获取参数

猜你喜欢

转载自blog.csdn.net/qq_19894073/article/details/80914541