《How tomcat works》读书笔记_tomcat默认连接器(2)

创建Request对象

这里写图片描述
在tomcat默认连接器中request对象是用org.apache.catalina.Request接口来表示的。这个接口由RequestBase类实现,并且它同时也是HttpRequest.接口的父接口。最终的实现类是HttpRequestImpl,它实现了HttpRequest接口。这里还有两个门面类:RequestFacade和HttpRequestFacade。上图就是request接口以及其实现类的UML图。
类似,Response对象的UML图如下:
这里写图片描述

处理请求:

之前我们已经了解了如何创建Reuest和Response对象,接下来主要介绍HttpProcessor的process方法,这个方法在HttpProcessor被分配一个socket后由其run方法调用。
其处理过程大致如下:

  • 解析connection
  • 解析request
  • 解析header
boolean ok = true;
boolean finishResponse = true;

process方法使用布尔值ok标注在方法执行过程中没有发生任何错误,布尔值finishResponse表示Response接口的finishResponse方法应该被调用。还有其它布尔值,如keepAlive,stopped,http11;keepAlive表示一个持久连接;stopped表示HttpProcessor实例已经被connector停止,process方法在这时也应该停止;http11表示这是一个来自HTTP1.1协议的请求。

        SocketInputStream input = null;
        OutputStream output = null;

        // Construct and initialize the objects we will need
        try {
            input = new SocketInputStream(socket.getInputStream(),
                                          connector.getBufferSize());
        } catch (Exception e) {
            log("process.create", e);
            ok = false;
        }

从前面的章节已经知道SocketInputStream类包装了一个socket的输入流,另外,SocketInputStream的构造方法中的buffer size是由connector传入的,并不是由HttpProcessor中的本地变量传入。这是因为对于默认连接器的使用都HttpProcessor是不可见的,把缓冲的大小放在connector中可以让任何人使用connector来设置其大小。

keepAlive = true;
while (!stopped && ok && keepAlive) {
...
}

接下来是一个while循环,这个循环会一直运行直到HttpProcessor停止、抛出异常或是connection被关闭。

在初始化request和response对象之后,process方法调用parseConnection、parseRequest和parseHeader来解析HTTP请求。

parseConnection方法:

    private void parseConnection(Socket socket)
        throws IOException, ServletException {

        if (debug >= 2)
            log("  parseConnection: address=" + socket.getInetAddress() +
                ", port=" + connector.getPort());
        ((HttpRequestImpl) request).setInet(socket.getInetAddress());
        if (proxyPort != 0)
            request.setServerPort(proxyPort);
        else
            request.setServerPort(serverPort);
        request.setSocket(socket);

    }

从socket中获取网络地址设置到HttpRequestImpl对象中,同时方法还检查是否使用了代理。

解析Request
同第三章

解析Header
在默认连接器中的parseHeader方法中,使用了HttpHeader和DefaultHeader类。HttpHeader类代表一个HTTP请求的header,和前面章节不同,HttpHeader中使用了char数组来减少使用String时高昂的代价。DefaultHeader是一个final类,它以char数组形式保存了HTTP请求header的信息。

简单的Container容器

        public void invoke(Request request, Response response)
            throws IOException, ServletException {

        String servletName = ((HttpServletRequest) request).getRequestURI();
        servletName = servletName.substring(servletName.lastIndexOf("/") + 1);
        URLClassLoader loader = null;
        try {
            URL[] urls = new URL[1];
            URLStreamHandler streamHandler = null;
            File classPath = new File(WEB_ROOT);
            String repository = (new URL("file", null,
                    classPath.getCanonicalPath() + File.separator)).toString();
            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((HttpServletRequest) request,
                    (HttpServletResponse) response);
        } catch (Exception e) {
            System.out.println(e.toString());
        } catch (Throwable e) {
            System.out.println(e.toString());
        }

    }

在ex04.pyrmont.startup.Bootstrap类启动程序时,首先会创建两个实例org.apache.catalina.connector.http.HttpConnector和SimpleContainer实例。调用connector的serContainer方法将SimpleContainer实例传递过去。由于connector继承了LifeCycle接口,所以接下来调用initialize和start方法来启动连接器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值