深入理解Tomcat系列之三 Connector

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                       

前言

Connector是Tomcat的连接器,其主要任务是负责处理浏览器发送过来的请求,并创建一个Request和Response的对象用于和浏览器交换数据,然后产生一个线程用于处理请求,Connector会把Request和Response对象传递给该线程,该线程的具体的处理过程是Container容器的事了。执行过程分为以下几个步骤

  1. 实例化Connector,构造一个Connector对象
  2. 调用Connector的initIntenal方法,初始化Connetor
  3. 调用ProtocolHanlder的init方法,完成ProtocolHanlder的初始化。这个过程包括了创建线程池并创建一个线程处理浏览器请求
  4. 调用Connector的startIntenal方法,启动Connector
  5. 调用ProtocolHandler的start方法,启动Protocolhanlder
  6. 调用MapperListener的start方法,启动监听器程序

为了对Connector的执行过程有一个大概的印象,可以参考下面的序列图:

Connector启动过程

注意:由于Tomcat还支持AJP协议,但为了简化,我画的这个序列图是基于Http协议的,这也是我们在Web开发中接触最多的协议了。

在深入Connector之前我们先看看Connector类的结构:

Connector属性
Connector部分方法

既然是处理浏览器请求,那么需要支持http协议,在Tomcat中有两种协议处理器:HTTP/1.1与AJP/1.3协议处理器。在server.xml中已经指明tomcat所支持的两种协议:

代码清单3-1:

    <Connector port="8080" protocol="HTTP/1.1"               connectionTimeout="20000"               redirectPort="8443" />    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
   
   
  • 1
  • 2
  • 3
  • 4

在tomcat中是怎么样分别处理这两种协议的呢,我们可以ProtocolHanlder类中找到答案:

ProtocolHanlder协议处理器

图中被选中的就是Tomcat默认使用协议处理器,其实现过程与Java标准Socket编程是一样的,在tomcat中可以使用Connetor类的setProtocol方法,看看源码就知道了:

代码清单3-2:

    public void setProtocol(String protocol) {        if (AprLifecycleListener.isAprAvailable()) {            if ("HTTP/1.1".equals(protocol)) {                setProtocolHandlerClassName                    ("org.apache.coyote.http11.Http11AprProtocol");            } else if ("AJP/1.3".equals(protocol)) {                setProtocolHandlerClassName                    ("org.apache.coyote.ajp.AjpAprProtocol");            } else if (protocol != null) {                setProtocolHandlerClassName(protocol);            } else {                setProtocolHandlerClassName                    ("org.apache.coyote.http11.Http11AprProtocol");            }        } else {            if ("HTTP/1.1".equals(protocol)) {                setProtocolHandlerClassName                    ("org.apache.coyote.http11.Http11Protocol");            } else if ("AJP/1.3".equals(protocol)) {                setProtocolHandlerClassName                    ("org.apache.coyote.ajp.AjpProtocol");            } else if (protocol != null) {                setProtocolHandlerClassName(protocol);            }        }    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

从第2个if子句的最后一个else可以知道tomcat默认使用的是http1.1协议。
我们再看看Connector的初始化过程:

代码清单3-3:

    @Override    protected void initInternal() throws LifecycleException {        super.initInternal();        // Initialize adapter        adapter = new CoyoteAdapter(this);        protocolHandler.setAdapter(adapter);        // Make sure parseBodyMethodsSet has a default        if( null == parseBodyMethodsSet ) {            setParseBodyMethods(getParseBodyMethods());        }        if (protocolHandler.isAprRequired() &&                !AprLifecycleListener.isAprAvailable()) {            throw new LifecycleException(                    sm.getString("coyoteConnector.protocolHandlerNoApr",                            getProtocolHandlerClassName()));        }        try {            protocolHandler.init();        } catch (Exception e) {            throw new LifecycleException                (sm.getString                 ("coyoteConnector.protocolHandlerInitializationFailed"), e);        }        // Initialize mapper listener        mapperListener.init();    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

从这段代码中可以看到:首先调用父类org.apache.catalina.util.LifecycleMBeanBase的初始化方法,然后创建一个Adapter,然后设置protocolHanlder(协议处理器)的Adapter,同时判断传过来的请求的请求方法(比如get或者post),如果没有指明请求方法,默认使用post处理,然后调用protocolHanlder的初始化方法,最后调用mapperListener的初始化方法,而mapperListener的初始化方法调用的是org.apache.catalina.util.LifecycleBase的init方法,我们重点关注protocolHanlder的初始化方法,具体是实现在AbstractProtocol抽象类中,其直接子类有AbstractAjpProtocol和AbstractHttp11Protocol,分别对应的是两种不同的处理协议,所以协议处理器的初始化方法是在其子抽象类(实现ProtocolHanlder接口的抽象类)来实现的,这里看看AbstractHttp11Protocol的初始化方法:

代码清单3-4:

    @Override    public void init() throws Exception {        if (getLog().isInfoEnabled())            getLog().info(sm.getString("abstractProtocolHandler.init",                    getName()));        if (oname == null) {            // Component not pre-registered so register it            oname = createObjectName();            if (oname != null) {                Registry.getRegistry(null, null).registerComponent(this, oname,                    null);            }        }        if (this.domain != null) {            try {                tpOname = new ObjectName(domain + ":" +                        "type=ThreadPool,name=" + getName());                Registry.getRegistry(null, null).registerComponent(endpoint,                        tpOname, null);            } catch (Exception e) {                getLog().error(sm.getString(                        "abstractProtocolHandler.mbeanRegistrationFailed",                        tpOname, getName()), e);            }            rgOname=new ObjectName(domain +                    ":type=GlobalRequestProcessor,name=" + getName());            Registry.getRegistry(null, null).registerComponent(                    getHandler().getGlobal(), rgOname, null );        }        String endpointName = getName();        endpoint.setName(endpointName.substring(1, endpointName.length()-1));        try {            endpoint.init();        } catch (Exception ex) {            getLog().error(sm.getString("abstractProtocolHandler.initError",                    getName()), ex);            throw ex;        }    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

打断点调试可以知道oname的值是Tomcat:type=ProtocolHandler,port=auto-1,address="127.0.0.1",tpOname是Tomcat:type=ProtocolHandler,port=auto-1,address="127.0.0.1",rOname是Tomcat:type=GlobalRequestProcessor,name="http-bio-127.0.0.1-auto-1",我们重点关注endpoint的init方法,主要完成以下几个过程:

  1. 设置线程接收数和最大连接数
  2. 创建线程池,启动监听的线程监听用户请求
  3. 启动一个线程处理请求

初始化完成Connector就可以启动了,启动阶段调用startInternal方法:

代码清单3-5:

    @Override    protected void startInternal() throws LifecycleException {        // Validate settings before starting        if (getPort() < 0) {            throw new LifecycleException(sm.getString(                    "coyoteConnector.invalidPort", Integer.valueOf(getPort())));        }        setState(LifecycleState.STARTING);        try {            protocolHandler.start();        } catch (Exception e) {            String errPrefix = "";            if(this.service != null) {                errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";            }            throw new LifecycleException                (errPrefix + " " + sm.getString                 ("coyoteConnector.protocolHandlerStartFailed"), e);        }        mapperListener.start();    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

可以看出Connector调用protocolHandler.start()方法,继续看看这个方法的源码:

代码清单3-6:

    @Override    public void start() throws Exception {        if (getLog().isInfoEnabled())            getLog().info(sm.getString("abstractProtocolHandler.start",                    getName()));        try {            endpoint.start();        } catch (Exception ex) {            getLog().error(sm.getString("abstractProtocolHandler.startError",                    getName()), ex);            throw ex;        }    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这个方法又调用了endpoint.start()方法:

代码清单3-7:

    public final void start() throws Exception {        if (bindState == BindState.UNBOUND) {            bind();            bindState = BindState.BOUND_ON_START;        }        startInternal();    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

然后又调用了org.apache.tomcat.util.net.AbstractEndpoint.startInternal()方法:

代码清单3-8:

    @Override    public void startInternal() throws Exception {        if (!running) {            running = true;            paused = false;            // Create worker collection            if (getExecutor() == null) {                createExecutor();            }            initializeConnectionLatch();            startAcceptorThreads();            // Start async timeout thread            Thread timeoutThread = new Thread(new AsyncTimeout(),                    getName() + "-AsyncTimeout");            timeoutThread.setPriority(threadPriority);            timeoutThread.setDaemon(true);            timeoutThread.start();        }    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  1. 设置线程接收数和最大连接数
  2. 创建线程池,启动监听的线程监听用户请求
  3. 启动一个线程处理异步请求

这里启动了一个异步线程处理请求,这个异步线程是如何执行的呢?

代码清单3-9:

    /**     * Async timeout thread     */    protected class AsyncTimeout implements Runnable {        /**         * The background thread that checks async requests and fires the         * timeout if there has been no activity.         */        @Override        public void run() {            // Loop until we receive a shutdown command            while (running) {                try {                    Thread.sleep(1000);                } catch (InterruptedException e) {                    // Ignore                }                long now = System.currentTimeMillis();                Iterator<SocketWrapper<Socket>> sockets =                    waitingRequests.iterator();                while (sockets.hasNext()) {                    SocketWrapper<Socket> socket = sockets.next();                    long access = socket.getLastAccess();                    if (socket.getTimeout() > 0 &&                            (now-access)>socket.getTimeout()) {                        processSocketAsync(socket,SocketStatus.TIMEOUT);                    }                }                // Loop if endpoint is paused                while (paused && running) {                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        // Ignore                    }                }            }        }    }    //processSocket    public boolean processSocketAsync(SocketWrapper<Socket> socket,            SocketStatus status) {        try {            synchronized (socket) {                if (waitingRequests.remove(socket)) {                    SocketProcessor proc = new SocketProcessor(socket,status);                    ClassLoader loader = Thread.currentThread().getContextClassLoader();                    try {                        //threads should not be created by the webapp classloader                        if (Constants.IS_SECURITY_ENABLED) {                            PrivilegedAction<Void> pa = new PrivilegedSetTccl(                                    getClass().getClassLoader());                            AccessController.doPrivileged(pa);                        } else {                            Thread.currentThread().setContextClassLoader(                                    getClass().getClassLoader());                        }                        // During shutdown, executor may be null - avoid NPE                        if (!running) {                            return false;                        }                        getExecutor().execute(proc);                        //TODO gotta catch RejectedExecutionException and properly handle it                    } finally {                        if (Constants.IS_SECURITY_ENABLED) {                            PrivilegedAction<Void> pa = new PrivilegedSetTccl(loader);                            AccessController.doPrivileged(pa);                        } else {                            Thread.currentThread().setContextClassLoader(loader);                        }                    }                }            }        } catch (Throwable t) {            ExceptionUtils.handleThrowable(t);            // This means we got an OOM or similar creating a thread, or that            // the pool and its queue are full            log.error(sm.getString("endpoint.process.fail"), t);            return false;        }        return true;    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

org.apache.tomcat.util.net.JIoEndpoint.SocketProcessor的职责是把具体的请求处理过程委派给org.apache.tomcat.util.net.JIoEndpoint.Handler,然后根据handler返回的不同SocketState,来决定是否关闭连接或者进行下一轮处理。

代码清单3-10:

public void run() {            boolean launch = false;            synchronized (socket) {                try {                    SocketState state = SocketState.OPEN;                    try {                        // SSL handshake                        serverSocketFactory.handshake(socket.getSocket());                    } catch (Throwable t) {                        ExceptionUtils.handleThrowable(t);                        if (log.isDebugEnabled()) {                            log.debug(sm.getString("endpoint.err.handshake"), t);                        }                        // Tell to close the socket                        state = SocketState.CLOSED;                    }                    if ((state != SocketState.CLOSED)) {                        if (status == null) {                            state = handler.process(socket, SocketStatus.OPEN_READ);                        } else {                            state = handler.process(socket,status);                        }                    }                    if (state == SocketState.CLOSED) {                        // Close socket                        if (log.isTraceEnabled()) {                            log.trace("Closing socket:"+socket);                        }                        countDownConnection();                        try {                            socket.getSocket().close();                        } catch (IOException e) {                            // Ignore                        }                    } else if (state == SocketState.OPEN ||                            state == SocketState.UPGRADING ||                            state == SocketState.UPGRADING_TOMCAT  ||                            state == SocketState.UPGRADED){                        socket.setKeptAlive(true);                        socket.access();                        launch = true;                    } else if (state == SocketState.LONG) {                        socket.access();                        waitingRequests.add(socket);                    }                } finally {                    if (launch) {                        try {                            getExecutor().execute(new SocketProcessor(socket, SocketStatus.OPEN_READ));                        } catch (RejectedExecutionException x) {                            log.warn("Socket reprocessing request was rejected for:"+socket,x);                            try {                                //unable to handle connection at this time                                handler.process(socket, SocketStatus.DISCONNECT);                            } finally {                                countDownConnection();                            }                        } catch (NullPointerException npe) {                            if (running) {                                log.error(sm.getString("endpoint.launch.fail"),                                        npe);                            }                        }                    }                }            }            socket = null;            // Finish up this request        }    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

其中的process方法主要完成对request的解析,包括请求头、请求行和请求体
代码清单3-11:

    //process method of org.apache.coyote.http11.AbstractHttp11Processor<S>.HttpProcessor extends org.apache.coyote.http11.AbstractHttp11Processor<S>    @Override    public SocketState process(SocketWrapper<S> socketWrapper)        throws IOException {        RequestInfo rp = request.getRequestProcessor();        rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);        // Setting up the I/O        setSocketWrapper(socketWrapper);        getInputBuffer().init(socketWrapper, endpoint);        getOutputBuffer().init(socketWrapper, endpoint);        // Flags        error = false;        keepAlive = true;        comet = false;        openSocket = false;        sendfileInProgress = false;        readComplete = true;        if (endpoint.getUsePolling()) {            keptAlive = false;        } else {            keptAlive = socketWrapper.isKeptAlive();        }        if (disableKeepAlive()) {            socketWrapper.setKeepAliveLeft(0);        }        while (!error && keepAlive && !comet && !isAsync() &&                upgradeInbound == null &&                httpUpgradeHandler == null && !endpoint.isPaused()) {            // Parsing the request header            try {                setRequestLineReadTimeout();                if (!getInputBuffer().parseRequestLine(keptAlive)) {                    if (handleIncompleteRequestLineRead()) {                        break;                    }                }                if (endpoint.isPaused()) {                    // 503 - Service unavailable                    response.setStatus(503);                    error = true;                } else {                    // Make sure that connectors that are non-blocking during                    // header processing (NIO) only set the start time the first                    // time a request is processed.                    if (request.getStartTime() < 0) {                        request.setStartTime(System.currentTimeMillis());                    }                    keptAlive = true;                    // Set this every time in case limit has been changed via JMX                    request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());                    // Currently only NIO will ever return false here                    if (!getInputBuffer().parseHeaders()) {                        // We've read part of the request, don't recycle it                        // instead associate it with the socket                        openSocket = true;                        readComplete = false;                        break;                    }                    if (!disableUploadTimeout) {                        setSocketTimeout(connectionUploadTimeout);                    }                }            } catch (IOException e) {                if (getLog().isDebugEnabled()) {                    getLog().debug(                            sm.getString("http11processor.header.parse"), e);                }                error = true;                break;            } catch (Throwable t) {                ExceptionUtils.handleThrowable(t);                UserDataHelper.Mode logMode = userDataHelper.getNextMode();                if (logMode != null) {                    String message = sm.getString(                            "http11processor.header.parse");                    switch (logMode) {                        case INFO_THEN_DEBUG:                            message += sm.getString(                                    "http11processor.fallToDebug");                            //$FALL-THROUGH$                        case INFO:                            getLog().info(message);                            break;                        case DEBUG:                            getLog().debug(message);                    }                }                // 400 - Bad Request                response.setStatus(400);                adapter.log(request, response, 0);                error = true;            }            if (!error) {                // Setting up filters, and parse some request headers                rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);                try {                    prepareRequest();                } catch (Throwable t) {                    ExceptionUtils.handleThrowable(t);                    if (getLog().isDebugEnabled()) {                        getLog().debug(sm.getString(                                "http11processor.request.prepare"), t);                    }                    // 400 - Internal Server Error                    response.setStatus(400);                    adapter.log(request, response, 0);                    error = true;                }            }            if (maxKeepAliveRequests == 1) {                keepAlive = false;            } else if (maxKeepAliveRequests > 0 &&                    socketWrapper.decrementKeepAlive() <= 0) {                keepAlive = false;            }            // Process the request in the adapter            if (!error) {                try {                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);                    adapter.service(request, response);                    if(keepAlive && !error) { // Avoid checking twice.                        error = response.getErrorException() != null ||                                (!isAsync() &&                                statusDropsConnection(response.getStatus()));                    }                    setCometTimeouts(socketWrapper);                } catch (InterruptedIOException e) {                    error = true;                } catch (HeadersTooLargeException e) {                    error = true;                    // The response should not have been committed but check it                    // anyway to be safe                    if (!response.isCommitted()) {                        response.reset();                        response.setStatus(500);                        response.setHeader("Connection", "close");                    }                } catch (Throwable t) {                    ExceptionUtils.handleThrowable(t);                    getLog().error(sm.getString(                            "http11processor.request.process"), t);                    // 500 - Internal Server Error                    response.setStatus(500);                    adapter.log(request, response, 0);                    error = true;                }            }            // Finish the handling of the request            rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);            if (!isAsync() && !comet) {                if (error) {                    getInputBuffer().setSwallowInput(false);                }                if (response.getStatus() < 200 || response.getStatus() > 299) {                    if (expectation) {                        // Client sent Expect: 100-continue but received a                        // non-2xx response. Disable keep-alive (if enabled) to                        // ensure the connection is closed. Some clients may                        // still send the body, some may send the next request.                        // No way to differentiate, so close the connection to                        // force the client to send the next request.                        getInputBuffer().setSwallowInput(false);                        keepAlive = false;                    }                }                endRequest();            }            rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);            // If there was an error, make sure the request is counted as            // and error, and update the statistics counter            if (error) {                response.setStatus(500);            }            request.updateCounters();            if (!isAsync() && !comet || error) {                getInputBuffer().nextRequest();                getOutputBuffer().nextRequest();            }            if (!disableUploadTimeout) {                if(endpoint.getSoTimeout() > 0) {                    setSocketTimeout(endpoint.getSoTimeout());                } else {                    setSocketTimeout(0);                }            }            rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);            if (breakKeepAliveLoop(socketWrapper)) {                break;            }        }        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);        }    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196

首先在Http11Processor的process方法里,会先从socket里读取http请求数据,并解析请求头,构造Request对象和Response对象,然后调用Adapter.service()方法。Adapter.service()完成请求行以及请求体的解析,并把解析出来的信息封装到Request和Response对象中,Adapter(确切说是org.apache.catalina.connector.CoyoteAdapter)是connector和container的桥梁,经过这一步,请求就从connector传递到container里了,Adapter.service()方法之后便将封装了Request以及Response对象的Socket传给Container容器了。
要注意的是:最先处理请求的Request是org.apache.coyote.Request类型,这是一个Tomcat中一个轻量级对象,完成基本的请求处理后很容易被JVM回收,那为什么不直接交给Connector.Request对象处理呢?由于后者是Servlet容器真正传递的对象其完成的职责比前者复杂,这里使用org.apache.coyote.Request主要减轻后者的任务负担,出于性能考虑才这么设计。
具体service方法清单如下:

代码清单3-12:

@Overridepublic void service(org.apache.coyote.Request req,                      org.apache.coyote.Response res)      throws Exception {      Request request = (Request) req.getNote(ADAPTER_NOTES);      Response response = (Response) res.getNote(ADAPTER_NOTES);      if (request == null) {          // Create objects          request = connector.createRequest();          request.setCoyoteRequest(req);          response = connector.createResponse();          response.setCoyoteResponse(res);          // Link objects          request.setResponse(response);          response.setRequest(request);          // Set as notes          req.setNote(ADAPTER_NOTES, request);          res.setNote(ADAPTER_NOTES, response);          // Set query string encoding          req.getParameters().setQueryStringEncoding              (connector.getURIEncoding());      }      if (connector.getXpoweredBy()) {          response.addHeader("X-Powered-By", POWERED_BY);      }      boolean comet = false;      boolean async = false;      try { // Parse and set Catalina and configuration //specific          // request parameters          req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());          //postParseRequest方法把CoyoteRequest转换为Connector.Request对象          //后一类型的对象才是在Tomcat容器流转时真正传递的对象          boolean postParseSuccess = postParseRequest(req, request, res, response);          if (postParseSuccess) {              //check valves if we support async              request.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());    // 调用Container容器的invoke方法,把请求交给Container容器              connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);              if (request.isComet()) {                  if (!response.isClosed() && !response.isError()) {                      if (request.getAvailable() || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {                          // Invoke a read event right away if there are available bytes                          if (event(req, res, SocketStatus.OPEN_READ)) {                              comet = true;                              res.action(ActionCode.COMET_BEGIN, null);                          }                      } else {                          comet = true;                          res.action(ActionCode.COMET_BEGIN, null);                      }                  } else {                      // Clear the filter chain, as otherwise it will not be reset elsewhere                      // since this is a Comet request                      request.setFilterChain(null);                  }              }          }          AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();          if (asyncConImpl != null) {              async = true;          } else if (!comet) {              request.finishRequest();              response.finishResponse();              if (postParseSuccess &&                      request.getMappingData().context != null) {                  ((Context) request.getMappingData().context).logAccess(                          request, response,                          System.currentTimeMillis() - req.getStartTime(),                          false);              }              req.action(ActionCode.POST_REQUEST , null);          }      } catch (IOException e) {          // Ignore      } finally {         //ignore      }  }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);这句代码中可以知道下一步的处理需要交给Container容器了。

经过上面一系列复杂的操作流程,Tomcat的Connector已经完成了protocol.start()方法,返回Connector的startIntenal方法,还有一个步骤要完成就是mapperListener.start()的方法了,整个执行过程比较简单,有两步:

  1. 执行Connector的startIntenal方法
  2. 执行MapperListener的startIntenal方法

代码清单3-14:

    @Override    public void startInternal() throws LifecycleException {        setState(LifecycleState.STARTING);        findDefaultHost();        Engine engine = (Engine) connector.getService().getContainer();        addListeners(engine);        Container[] conHosts = engine.findChildren();        for (Container conHost : conHosts) {            Host host = (Host) conHost;            if (!LifecycleState.NEW.equals(host.getState())) {                // Registering the host will register the context and wrappers                registerHost(host);            }        }    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

首先注册已初始化的组件,然后为这些组件添加监听器,最后添加容器之间的映射关系。这样经过上面两个大步骤以及N个小步骤,我们的Connector才算启动完毕,可谓是路途艰辛啊!

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_43667968/article/details/84104082