tomcat处理请求

参考资料:Tomcat7.0源码分析——请求原理分析(中)


客户端和服务器之间的链接建立了,那接下来就要接受数据,处理请求,我们来看看是怎样实现的。


1、我们之前创建了Acceptor线程类接受连接,成功连接以后就要进行处理socket了。

    protected class Acceptor extends AbstractEndpoint.Acceptor {

        @Override
        public void run() {
            int errorDelay = 0;
            while (running) {
                while (paused && running) {
                    state = AcceptorState.PAUSED;
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                    }
                }
                if (!running) {
                    break;
                }
                state = AcceptorState.RUNNING;
                try {
                    countUpOrAwaitConnection();
                    Socket socket = null;
                    try {
                        socket = serverSocketFactory.acceptSocket(serverSocket);
                    } catch (IOException ioe) {
                        errorDelay = handleExceptionWithDelay(errorDelay);
                        throw ioe;
                    }
                    errorDelay = 0;
                    if (running && !paused && setSocketOptions(socket)) {
                        // 在这里处理请求
                        if (!processSocket(socket)) {
                            closeSocket(socket);
                        }
                    } else {
                        closeSocket(socket);
                    }
                } catch (IOException x) {
                    if (running) {
                        log.error(sm.getString("endpoint.accept.fail"), x);
                    }
                } catch (NullPointerException npe) {
                    if (running) {
                        log.error(sm.getString("endpoint.accept.fail"), npe);
                    }
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    log.error(sm.getString("endpoint.accept.fail"), t);
                }
            }
            state = AcceptorState.ENDED;
        }
    }



2、进入processSocket方法,我们可以看到处理socket请求的是另一个线程类SocketProcessor。


    protected class SocketProcessor implements Runnable {

        // 包装socket
        protected SocketWrapper<Socket> socket = null;
        protected SocketStatus status = null;

        public SocketProcessor(SocketWrapper<Socket> socket) {
            if (socket == null) throw new NullPointerException();
            this.socket = socket;
        }

        public SocketProcessor(SocketWrapper<Socket> socket, SocketStatus status) {
            this(socket);
            this.status = status;
        }

        @Override
        public void run() {
            boolean launch = false;
            synchronized (socket) {
                try {
                    SocketState state = SocketState.OPEN;
                    try {
                        serverSocketFactory.handshake(socket.getSocket());
                    } catch (Throwable t) {
                        ExceptionUtils.handleThrowable(t);
                        if (log.isDebugEnabled()) {
                            log.debug(sm.getString("endpoint.err.handshake"), t);
                        }
                        state = SocketState.CLOSED;
                    }
                    if ((state != SocketState.CLOSED)) {
                        if (status == null) {
                            // 处理请求的方法
                            state = handler.process(socket, SocketStatus.OPEN);
                        } else {
                            state = handler.process(socket, status);
                        }
                    }
                    if (state == SocketState.CLOSED) {
                        if (log.isTraceEnabled()) {
                            log.trace("Closing socket:" + socket);
                        }
                        countDownConnection();
                        try {
                            socket.getSocket().close();
                        } catch (IOException e) {
                        }
                    } else if (state == SocketState.OPEN) {
                        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));
                        } catch (NullPointerException npe) {
                            if (running) {
                                log.error(sm.getString("endpoint.launch.fail"), npe);
                            }
                        }
                    }
                }
            }
            socket = null;
        }
    }




3、进入process方法

public SocketState process(SocketWrapper<S> socket, SocketStatus status) {
            P processor = connections.remove(socket.getSocket());
            if (getLog().isDebugEnabled()) {
                getLog().debug("process() entry " +
                        "Socket: [" + logHashcode(socket.getSocket()) + "], " +
                        "Processor [" + logHashcode(processor) + "]");
            }
            socket.setAsync(false);
            try {
                if (processor == null) {
                    processor = recycledProcessors.poll();
                }
                if (processor == null) {
                    // 创建Http请求处理器
                    processor = createProcessor();
                }
                if (getLog().isDebugEnabled()) {
                    getLog().debug("process() gotProcessor " +
                            "Socket: [" + logHashcode(socket.getSocket()) + "], " +
                            "Processor [" + logHashcode(processor) + "]");
                }
                initSsl(socket, processor);
                SocketState state = SocketState.CLOSED;
                do {
                    if (processor.isAsync() || state == SocketState.ASYNC_END) {
                        state = processor.asyncDispatch(status);
                        if (getLog().isDebugEnabled()) {
                            getLog().debug("process() asyncDispatch " +
                                    "Socket: [" + logHashcode(socket.getSocket()) + "], " +
                                    "Processor: [" + logHashcode(processor) + "], " +
                                    "State: [" + state.toString() + "]");
                        }
                    } else if (processor.isComet()) {
                        state = processor.event(status);
                        if (getLog().isDebugEnabled()) {
                            getLog().debug("process() event " +
                                    "Socket: [" + logHashcode(socket.getSocket()) + "], " +
                                    "Processor: [" + logHashcode(processor) + "], " +
                                    "State: [" + state.toString() + "]");
                        }
                    } else {
                        // 同步处理socket
                        state = processor.process(socket);
                        if (getLog().isDebugEnabled()) {
                            getLog().debug("process() process " +
                                    "Socket: [" + logHashcode(socket.getSocket()) + "], " +
                                    "Processor: [" + logHashcode(processor) + "], " +
                                    "State: [" + state.toString() + "]");
                        }
                    }
                    if (state != SocketState.CLOSED && processor.isAsync()) {
                        state = processor.asyncPostProcess();
                        if (getLog().isDebugEnabled()) {
                            getLog().debug("process() asyncPostProcess " +
                                    "Socket: [" + logHashcode(socket.getSocket()) + "], " +
                                    "Processor: [" + logHashcode(processor) + "], " +
                                    "State: [" + state.toString() + "]");
                        }

                    }
                } while (state == SocketState.ASYNC_END);
                if (state == SocketState.LONG) {
                    longPoll(socket, processor);
                } else if (state == SocketState.OPEN) {
                    release(socket, processor, false, true);
                } else if (state == SocketState.SENDFILE) {
                    release(socket, processor, false, false);
                } else {
                    release(socket, processor, true, false);
                }
                return state;
            } catch (java.net.SocketException e) {
                getLog().debug(sm.getString("ajpprotocol.proto.socketexception.debug"), e);
            } catch (java.io.IOException e) {
                getLog().debug(sm.getString("ajpprotocol.proto.ioexception.debug"), e);
            }
            catch (Throwable e) {
                ExceptionUtils.handleThrowable(e);
                getLog().error(sm.getString("ajpprotocol.proto.error"), e);
            }
            release(socket, processor, true, false);
            return SocketState.CLOSED;
        }


4、在process方法中,解析成Request对象,交给CoyoteAdapter 进行处理

    @Override
    public SocketState process(SocketWrapper<S> socketWrapper) throws IOException {
        RequestInfo rp = request.getRequestProcessor();
        rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
        setSocketWrapper(socketWrapper);
        getInputBuffer().init(socketWrapper, endpoint);
        getOutputBuffer().init(socketWrapper, endpoint);
        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() &&
                !endpoint.isPaused()) {
            try {
                setRequestLineReadTimeout();
                if (!getInputBuffer().parseRequestLine(keptAlive)) {
                    if (handleIncompleteRequestLineRead()) {
                        break;
                    }
                }
                if (endpoint.isPaused()) {
                    response.setStatus(503);
                    error = true;
                } else {
                    request.setStartTime(System.currentTimeMillis());
                    keptAlive = true;
                    if (!getInputBuffer().parseHeaders()) {
                        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);
                if (getLog().isDebugEnabled()) {
                    getLog().debug(sm.getString("http11processor.header.parse"), t);
                }
                response.setStatus(400);
                adapter.log(request, response, 0);
                error = true;
            }
            if (!error) {
                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);
                    }
                    response.setStatus(400);
                    adapter.log(request, response, 0);
                    error = true;
                }
            }
            if (maxKeepAliveRequests == 1) {
                keepAlive = false;
            } else if (maxKeepAliveRequests > 0 &&
                    socketWrapper.decrementKeepAlive() <= 0) {
                keepAlive = false;
            }
            if (!error) {
                try {
                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                    // 把请求交给CoyoteAdapter 来处理
                    adapter.service(request, response);
                    if (keepAlive && !error) {
                        error = response.getErrorException() != null || (!isAsync() && statusDropsConnection(response.getStatus()));
                    }
                    setCometTimeouts(socketWrapper);
                } catch (InterruptedIOException e) {
                    error = true;
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    getLog().error(sm.getString("http11processor.request.process"), t);
                    response.setStatus(500);
                    adapter.log(request, response, 0);
                    error = true;
                }
            }
            rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
            if (!isAsync() && !comet) {
                if (error) {
                   getInputBuffer().setSwallowInput(false);
                }
                endRequest();
            }
            rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
            if (error) {
                response.setStatus(500);
            }
            request.updateCounters();
            if (!isAsync() && !comet || error) {
                getInputBuffer().nextRequest();
                getOutputBuffer().nextRequest();
            }
            if (!disableUploadTimeout) {
                setSocketTimeout(endpoint.getSoTimeout());
            }
            rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
            if (breakKeepAliveLoop(socketWrapper)) {
                break;
            }
        }
        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
        if (error || endpoint.isPaused()) {
            return SocketState.CLOSED;
        } else if (isAsync() || comet) {
            return SocketState.LONG;
        } else {
            if (sendfileInProgress) {
                return SocketState.SENDFILE;
            } else {
                if (openSocket) {
                    if (readComplete) {
                        return SocketState.OPEN;
                    } else {
                        return SocketState.LONG;
                    }
                } else {
                    return SocketState.CLOSED;
                }
            }
        }
    }


5、CoyoteAdapter 的service方法继续解析请求

@Override
    public 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) {
            request = connector.createRequest();
            request.setCoyoteRequest(req);
            response = connector.createResponse();
            response.setCoyoteResponse(res);
            request.setResponse(response);
            response.setRequest(request);
            req.setNote(ADAPTER_NOTES, request);
            res.setNote(ADAPTER_NOTES, response);
            req.getParameters().setQueryStringEncoding
                    (connector.getURIEncoding());
        }
        if (connector.getXpoweredBy()) {
            response.addHeader("X-Powered-By", POWERED_BY);
        }
        boolean comet = false;
        boolean async = false;
        try {
            req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
            // 解析请求
            boolean postParseSuccess = postParseRequest(req, request, res, response);
            if (postParseSuccess) {
                request.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());
                // 处理请求
                connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
                if (request.isComet()) {
                    if (!response.isClosed() && !response.isError()) {
                        if (request.getAvailable() || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {
                            if (event(req, res, SocketStatus.OPEN)) {
                                comet = true;
                                res.action(ActionCode.COMET_BEGIN, null);
                            }
                        } else {
                            comet = true;
                            res.action(ActionCode.COMET_BEGIN, null);
                        }
                    } else {
                        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) {
        } finally {
            req.getRequestProcessor().setWorkerThreadName(null);
            if (!comet && !async) {
                request.recycle();
                response.recycle();
            } else {
                request.clearEncoders();
                response.clearEncoders();
            }
        }
    }


    protected boolean postParseRequest(org.apache.coyote.Request req, Request request, org.apache.coyote.Response res, Response response) throws Exception {
        if (!req.scheme().isNull()) {
            request.setSecure(req.scheme().equals("https"));
        } else {
            req.scheme().setString(connector.getScheme());
            request.setSecure(connector.getSecure());
        }
        String proxyName = connector.getProxyName();
        int proxyPort = connector.getProxyPort();
        if (proxyPort != 0) {
            req.setServerPort(proxyPort);
        }
        if (proxyName != null) {
            req.serverName().setString(proxyName);
        }
        MessageBytes decodedURI = req.decodedURI();
        decodedURI.duplicate(req.requestURI());
        parsePathParameters(req, request);
        try {
            req.getURLDecoder().convert(decodedURI, false);
        } catch (IOException ioe) {
            res.setStatus(400);
            res.setMessage("Invalid URI: " + ioe.getMessage());
            connector.getService().getContainer().logAccess(request, response, 0, true);
            return false;
        }
        if (!normalize(req.decodedURI())) {
            res.setStatus(400);
            res.setMessage("Invalid URI");
            connector.getService().getContainer().logAccess(request, response, 0, true);
            return false;
        }
        convertURI(decodedURI, request);
        if (!checkNormalize(req.decodedURI())) {
            res.setStatus(400);
            res.setMessage("Invalid URI character encoding");
            connector.getService().getContainer().logAccess(request, response, 0, true);
            return false;
        }
        String principal = req.getRemoteUser().toString();
        if (principal != null) {
            request.setUserPrincipal(new CoyotePrincipal(principal));
        }
        String authtype = req.getAuthType().toString();
        if (authtype != null) {
            request.setAuthType(authtype);
        }
        MessageBytes serverName;
        if (connector.getUseIPVHosts()) {
            serverName = req.localName();
            if (serverName.isNull()) {
                res.action(ActionCode.REQ_LOCAL_NAME_ATTRIBUTE, null);
            }
        } else {
            serverName = req.serverName();
        }
        if (request.isAsyncStarted()) {
            request.getMappingData().recycle();
        }
        boolean mapRequired = true;
        String version = null;
        while (mapRequired) {
            if (version != null) {
                mapRequired = false;
            }
            connector.getMapper().map(serverName, decodedURI, version,
                    request.getMappingData());
            request.setContext((Context) request.getMappingData().context);
            request.setWrapper((Wrapper) request.getMappingData().wrapper);
            if (request.getMappingData().contexts == null) {
                mapRequired = false;
            }
            if (request.getContext() == null) {
                res.setStatus(404);
                res.setMessage("Not found");
                Host host = request.getHost();
                if (host != null) {
                    host.logAccess(request, response, 0, true);
                }
                return false;
            }
            String sessionID = null;
            if (request.getServletContext().getEffectiveSessionTrackingModes()
                    .contains(SessionTrackingMode.URL)) {
                sessionID = request.getPathParameter(
                        SessionConfig.getSessionUriParamName(
                                request.getContext()));
                if (sessionID != null) {
                    request.setRequestedSessionId(sessionID);
                    request.setRequestedSessionURL(true);
                }
            }
            parseSessionCookiesId(req, request);
            parseSessionSslId(request);
            sessionID = request.getRequestedSessionId();
            if (mapRequired) {
                if (sessionID == null) {
                    mapRequired = false;
                } else {
                    Object[] objs = request.getMappingData().contexts;
                    for (int i = (objs.length); i > 0; i--) {
                        Context ctxt = (Context) objs[i - 1];
                        if (ctxt.getManager().findSession(sessionID) != null) {
                            if (ctxt.equals(request.getMappingData().context)) {
                                mapRequired = false;
                            } else {
                                version = ctxt.getWebappVersion();
                                request.getMappingData().recycle();
                                break;
                            }
                        }
                    }
                    if (version == null) {
                        mapRequired = false;
                    }
                }
            }
        }
        MessageBytes redirectPathMB = request.getMappingData().redirectPath;
        if (!redirectPathMB.isNull()) {
            String redirectPath = urlEncoder.encode(redirectPathMB.toString());
            String query = request.getQueryString();
            if (request.isRequestedSessionIdFromURL()) {
                redirectPath = redirectPath + ";" +
                        SessionConfig.getSessionUriParamName(
                                request.getContext()) +
                        "=" + request.getRequestedSessionId();
            }
            if (query != null) {
                redirectPath = redirectPath + "?" + query;
            }
            response.sendRedirect(redirectPath);
            request.getContext().logAccess(request, response, 0, true);
            return false;
        }
        if (!connector.getAllowTrace()
                && req.method().equalsIgnoreCase("TRACE")) {
            Wrapper wrapper = request.getWrapper();
            String header = null;
            if (wrapper != null) {
                String[] methods = wrapper.getServletMethods();
                if (methods != null) {
                    for (int i = 0; i < methods.length; i++) {
                        if ("TRACE".equals(methods[i])) {
                            continue;
                        }
                        if (header == null) {
                            header = methods[i];
                        } else {
                            header += ", " + methods[i];
                        }
                    }
                }
            }
            res.setStatus(405);
            res.addHeader("Allow", header);
            res.setMessage("TRACE method is not allowed");
            request.getContext().logAccess(request, response, 0, true);
            return false;
        }
        return true;
    }


终于看到真正处理请求的方法了。。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值