千家信息网

Tomcat9如何实现请求处理

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,这篇文章给大家分享的是有关Tomcat9如何实现请求处理的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。请求处理Tomcat对于HTTP请求,会由Connector监听的端口
千家信息网最后更新 2026年11月04日Tomcat9如何实现请求处理

这篇文章给大家分享的是有关Tomcat9如何实现请求处理的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

请求处理


Tomcat对于HTTP请求,会由Connector监听的端口,通过线程池的处理进行多线程的处理。
此线程池默认的最小线程数minSpareThreads等于10,最大线程数maxThreads等于200,我们可以在server.xml的Connector配置中调整它们的大小。
之后,采用责任链模式,通过容器的管道对请求进行处理,最终调用用户开发的Filter和Servlet。

源码分析

org.apache.catalina.connector.Connector
 public Connector(String protocol) {        boolean aprConnector = AprLifecycleListener.isAprAvailable() &&                AprLifecycleListener.getUseAprConnector();        if ("HTTP/1.1".equals(protocol) || protocol == null) {            if (aprConnector) {                protocolHandlerClassName = "org.apache.coyote.http11.Http11AprProtocol";            } else {                protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";            }        } else if ("AJP/1.3".equals(protocol)) {            if (aprConnector) {                protocolHandlerClassName = "org.apache.coyote.ajp.AjpAprProtocol";            } else {                protocolHandlerClassName = "org.apache.coyote.ajp.AjpNioProtocol";            }        } else {            protocolHandlerClassName = protocol;        }        // Instantiate protocol handler        ProtocolHandler p = null;        try {            Class clazz = Class.forName(protocolHandlerClassName);            p = (ProtocolHandler) clazz.getConstructor().newInstance();        } catch (Exception e) {            log.error(sm.getString(                    "coyoteConnector.protocolHandlerInstantiationFailed"), e);        } finally {            this.protocolHandler = p;        }        // Default for Connector depends on this system property        setThrowOnFailure(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"));    }

在Connector的构造方法中,会根据配置的不同协议,创建不同协议处理类,Tomcat9中默认的配置为protocol="HTTP/1.1",对应的类为Http11NioProtocol

org.apache.coyote.http11.Http11NioProtocol
public Http11NioProtocol() {        super(new NioEndpoint());    }

Http11NioProtocol的构造方中,会创建NioEndpoint,NioEndpoint会处理socket的接口以及请求的调用。

org.apache.tomcat.util.net.NioEndpoint
@Override    public void startInternal() throws Exception {        if (!running) {            running = true;            paused = false;            if (socketProperties.getProcessorCache() != 0) {                processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,                        socketProperties.getProcessorCache());            }            if (socketProperties.getEventCache() != 0) {                eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,                        socketProperties.getEventCache());            }            if (socketProperties.getBufferPool() != 0) {                nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,                        socketProperties.getBufferPool());            }            // Create worker collection            if (getExecutor() == null) {                createExecutor();            }            initializeConnectionLatch();            // Start poller thread            poller = new Poller();            Thread pollerThread = new Thread(poller, getName() + "-ClientPoller");            pollerThread.setPriority(threadPriority);            pollerThread.setDaemon(true);            pollerThread.start();            startAcceptorThread();        }    }    protected void startAcceptorThread() {        acceptor = new Acceptor<>(this);        String threadName = getName() + "-Acceptor";        acceptor.setThreadName(threadName);        Thread t = new Thread(acceptor, threadName);        t.setPriority(getAcceptorThreadPriority());        t.setDaemon(getDaemon());        t.start();    }

NioEndpoint的startInternal方法中会启动Poller线程和Acceptor线程

org.apache.tomcat.util.net.Acceptor
@Override    public void run() {        int errorDelay = 0;        // Loop until we receive a shutdown command        while (endpoint.isRunning()) {            // Loop if endpoint is paused            while (endpoint.isPaused() && endpoint.isRunning()) {                state = AcceptorState.PAUSED;                try {                    Thread.sleep(50);                } catch (InterruptedException e) {                    // Ignore                }            }            if (!endpoint.isRunning()) {                break;            }            state = AcceptorState.RUNNING;            try {                //if we have reached max connections, wait                endpoint.countUpOrAwaitConnection();                // Endpoint might have been paused while waiting for latch                // If that is the case, don't accept new connections                if (endpoint.isPaused()) {                    continue;                }                U socket = null;                try {                    // Accept the next incoming connection from the server                    // socket                    socket = endpoint.serverSocketAccept();                } catch (Exception ioe) {                    // We didn't get a socket                    endpoint.countDownConnection();                    if (endpoint.isRunning()) {                        // Introduce delay if necessary                        errorDelay = handleExceptionWithDelay(errorDelay);                        // re-throw                        throw ioe;                    } else {                        break;                    }                }                // Successful accept, reset the error delay                errorDelay = 0;                // Configure the socket                if (endpoint.isRunning() && !endpoint.isPaused()) {                    // setSocketOptions() will hand the socket off to                    // an appropriate processor if successful                    if (!endpoint.setSocketOptions(socket)) {                        endpoint.closeSocket(socket);                    }                } else {                    endpoint.destroySocket(socket);                }            } catch (Throwable t) {                ExceptionUtils.handleThrowable(t);                String msg = sm.getString("endpoint.accept.fail");                // APR specific.                // Could push this down but not sure it is worth the trouble.                if (t instanceof Error) {                    Error e = (Error) t;                    if (e.getError() == 233) {                        // Not an error on HP-UX so log as a warning                        // so it can be filtered out on that platform                        // See bug 50273                        log.warn(msg, t);                    } else {                        log.error(msg, t);                    }                } else {                        log.error(msg, t);                }            }        }        state = AcceptorState.ENDED;    }

Acceptor的run方法中,endpoint.serverSocketAccept()会调用NioEndpoint的具体实现来开启对应端口的TCP监听,当端口有请求时,则endpoint.setSocketOptions(socket)进行具体处理

org.apache.tomcat.util.net.NioEndpoint.setSocketOptions
protected boolean setSocketOptions(SocketChannel socket) {        // Process the connection        try {            // Disable blocking, polling will be used            socket.configureBlocking(false);            Socket sock = socket.socket();            socketProperties.setProperties(sock);            NioChannel channel = null;            if (nioChannels != null) {                channel = nioChannels.pop();            }            if (channel == null) {                SocketBufferHandler bufhandler = new SocketBufferHandler(                        socketProperties.getAppReadBufSize(),                        socketProperties.getAppWriteBufSize(),                        socketProperties.getDirectBuffer());                if (isSSLEnabled()) {                    channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);                } else {                    channel = new NioChannel(socket, bufhandler);                }            } else {                channel.setIOChannel(socket);                channel.reset();            }            NioSocketWrapper socketWrapper = new NioSocketWrapper(channel, this);            channel.setSocketWrapper(socketWrapper);            socketWrapper.setReadTimeout(getConnectionTimeout());            socketWrapper.setWriteTimeout(getConnectionTimeout());            socketWrapper.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());            socketWrapper.setSecure(isSSLEnabled());            poller.register(channel, socketWrapper);            return true;        } catch (Throwable t) {            ExceptionUtils.handleThrowable(t);            try {                log.error(sm.getString("endpoint.socketOptionsError"), t);            } catch (Throwable tt) {                ExceptionUtils.handleThrowable(tt);            }        }        // Tell to close the socket        return false;    }

在setSocketOptions方法中,主要逻辑为将socket请求放入Poller的队列中,在之前启动的Poller线程会不断的从队列中获取请求。

org.apache.tomcat.util.net.NioEndpoint$Poller
@Override        public void run() {            // Loop until destroy() is called            while (true) {                boolean hasEvents = false;                try {                    if (!close) {                        hasEvents = events();                        if (wakeupCounter.getAndSet(-1) > 0) {                            // If we are here, means we have other stuff to do                            // Do a non blocking select                            keyCount = selector.selectNow();                        } else {                            keyCount = selector.select(selectorTimeout);                        }                        wakeupCounter.set(0);                    }                    if (close) {                        events();                        timeout(0, false);                        try {                            selector.close();                        } catch (IOException ioe) {                            log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe);                        }                        break;                    }                } catch (Throwable x) {                    ExceptionUtils.handleThrowable(x);                    log.error(sm.getString("endpoint.nio.selectorLoopError"), x);                    continue;                }                // Either we timed out or we woke up, process events first                if (keyCount == 0) {                    hasEvents = (hasEvents | events());                }                Iterator iterator =                    keyCount > 0 ? selector.selectedKeys().iterator() : null;                // Walk through the collection of ready keys and dispatch                // any active event.                while (iterator != null && iterator.hasNext()) {                    SelectionKey sk = iterator.next();                    NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment();                    // Attachment may be null if another thread has called                    // cancelledKey()                    if (socketWrapper == null) {                        iterator.remove();                    } else {                        iterator.remove();                        processKey(sk, socketWrapper);                    }                }                // Process timeouts                timeout(keyCount,hasEvents);            }            getStopLatch().countDown();        }        protected void processKey(SelectionKey sk, NioSocketWrapper socketWrapper) {            try {                if (close) {                    cancelledKey(sk, socketWrapper);                } else if (sk.isValid() && socketWrapper != null) {                    if (sk.isReadable() || sk.isWritable()) {                        if (socketWrapper.getSendfileData() != null) {                            processSendfile(sk, socketWrapper, false);                        } else {                            unreg(sk, socketWrapper, sk.readyOps());                            boolean closeSocket = false;                            // Read goes before write                            if (sk.isReadable()) {                                if (socketWrapper.readOperation != null) {                                    if (!socketWrapper.readOperation.process()) {                                        closeSocket = true;                                    }                                } else if (!processSocket(socketWrapper, SocketEvent.OPEN_READ, true)) {                                    closeSocket = true;                                }                            }                            if (!closeSocket && sk.isWritable()) {                                if (socketWrapper.writeOperation != null) {                                    if (!socketWrapper.writeOperation.process()) {                                        closeSocket = true;                                    }                                } else if (!processSocket(socketWrapper, SocketEvent.OPEN_WRITE, true)) {                                    closeSocket = true;                                }                            }                            if (closeSocket) {                                cancelledKey(sk, socketWrapper);                            }                        }                    }                } else {                    // Invalid key                    cancelledKey(sk, socketWrapper);                }            } catch (CancelledKeyException ckx) {                cancelledKey(sk, socketWrapper);            } catch (Throwable t) {                ExceptionUtils.handleThrowable(t);                log.error(sm.getString("endpoint.nio.keyProcessingError"), t);            }        }    protected void processKey(SelectionKey sk, NioSocketWrapper socketWrapper) {            try {                if (close) {                    cancelledKey(sk, socketWrapper);                } else if (sk.isValid() && socketWrapper != null) {                    if (sk.isReadable() || sk.isWritable()) {                        if (socketWrapper.getSendfileData() != null) {                            processSendfile(sk, socketWrapper, false);                        } else {                            unreg(sk, socketWrapper, sk.readyOps());                            boolean closeSocket = false;                            // Read goes before write                            if (sk.isReadable()) {                                if (socketWrapper.readOperation != null) {                                    if (!socketWrapper.readOperation.process()) {                                        closeSocket = true;                                    }                                } else if (!processSocket(socketWrapper, SocketEvent.OPEN_READ, true)) {                                    closeSocket = true;                                }                            }                            if (!closeSocket && sk.isWritable()) {                                if (socketWrapper.writeOperation != null) {                                    if (!socketWrapper.writeOperation.process()) {                                        closeSocket = true;                                    }                                } else if (!processSocket(socketWrapper, SocketEvent.OPEN_WRITE, true)) {                                    closeSocket = true;                                }                            }                            if (closeSocket) {                                cancelledKey(sk, socketWrapper);                            }                        }                    }                } else {                    // Invalid key                    cancelledKey(sk, socketWrapper);                }            } catch (CancelledKeyException ckx) {                cancelledKey(sk, socketWrapper);            } catch (Throwable t) {                ExceptionUtils.handleThrowable(t);                log.error(sm.getString("endpoint.nio.keyProcessingError"), t);            }        }

在run方法中,会轮询Poller队列中的请求,并调用processKey方法进行处理,并最终调用processSocket方法

public boolean processSocket(SocketWrapperBase socketWrapper,            SocketEvent event, boolean dispatch) {        try {            if (socketWrapper == null) {                return false;            }            SocketProcessorBase sc = null;            if (processorCache != null) {                sc = processorCache.pop();            }            if (sc == null) {                sc = createSocketProcessor(socketWrapper, event);            } else {                sc.reset(socketWrapper, event);            }            Executor executor = getExecutor();            if (dispatch && executor != null) {                executor.execute(sc);            } else {                sc.run();            }        } catch (RejectedExecutionException ree) {            getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);            return false;        } 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            getLog().error(sm.getString("endpoint.process.fail"), t);            return false;        }        return true;    }

在processSocket会将请求封装为SocketProcessor对象,并多线程进行处理。

SocketProcessor
protected class SocketProcessor extends SocketProcessorBase {        public SocketProcessor(SocketWrapperBase socketWrapper, SocketEvent event) {            super(socketWrapper, event);        }        @Override        protected void doRun() {            NioChannel socket = socketWrapper.getSocket();            SelectionKey key = socket.getIOChannel().keyFor(socket.getSocketWrapper().getPoller().getSelector());            Poller poller = NioEndpoint.this.poller;            if (poller == null) {                socketWrapper.close();                return;            }            try {                int handshake = -1;                try {                    if (key != null) {                        if (socket.isHandshakeComplete()) {                            // No TLS handshaking required. Let the handler                            // process this socket / event combination.                            handshake = 0;                        } else if (event == SocketEvent.STOP || event == SocketEvent.DISCONNECT ||                                event == SocketEvent.ERROR) {                            // Unable to complete the TLS handshake. Treat it as                            // if the handshake failed.                            handshake = -1;                        } else {                            handshake = socket.handshake(key.isReadable(), key.isWritable());                            // The handshake process reads/writes from/to the                            // socket. status may therefore be OPEN_WRITE once                            // the handshake completes. However, the handshake                            // happens when the socket is opened so the status                            // must always be OPEN_READ after it completes. It                            // is OK to always set this as it is only used if                            // the handshake completes.                            event = SocketEvent.OPEN_READ;                        }                    }                } catch (IOException x) {                    handshake = -1;                    if (log.isDebugEnabled()) log.debug("Error during SSL handshake",x);                } catch (CancelledKeyException ckx) {                    handshake = -1;                }                if (handshake == 0) {                    SocketState state = SocketState.OPEN;                    // Process the request from this socket                    if (event == null) {                        state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);                    } else {                        state = getHandler().process(socketWrapper, event);                    }                    if (state == SocketState.CLOSED) {                        poller.cancelledKey(key, socketWrapper);                    }                } else if (handshake == -1 ) {                    getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);                    poller.cancelledKey(key, socketWrapper);                } else if (handshake == SelectionKey.OP_READ){                    socketWrapper.registerReadInterest();                } else if (handshake == SelectionKey.OP_WRITE){                    socketWrapper.registerWriteInterest();                }            } catch (CancelledKeyException cx) {                poller.cancelledKey(key, socketWrapper);            } catch (VirtualMachineError vme) {                ExceptionUtils.handleThrowable(vme);            } catch (Throwable t) {                log.error(sm.getString("endpoint.processing.fail"), t);                poller.cancelledKey(key, socketWrapper);            } finally {                socketWrapper = null;                event = null;                //return to cache                if (running && !paused && processorCache != null) {                    processorCache.push(this);                }            }        }    }public SocketState process(SocketWrapperBase wrapper, SocketEvent status) {...省略其他代码...if (processor == null) {                    processor = getProtocol().createProcessor();                    register(processor);                }...省略其他代码...state = processor.process(wrapper, status);} protected Processor createProcessor() {        Http11Processor processor = new Http11Processor(this, adapter);        return processor;    }

在SocketProcessor中,多线程run方法会调用dorun方法,其中会调用getHandler().process()方法来进行后续处理,在process方法中会实例化processor,并调用processor.process,HTTP/1.1协议对应的processor为Http11Processor
在Http11Processor中,会对HTTP请求的头部信息进行解析,此处代码较多,读者可自行查看Http11Processor.service方法。
解析完请求头后,调用CoyoteAdapter.service方法

CoyoteAdapter
 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) {            // 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().setQueryStringCharset(connector.getURICharset());        }        if (connector.getXpoweredBy()) {            response.addHeader("X-Powered-By", POWERED_BY);        }        boolean async = false;        boolean postParseSuccess = false;        req.getRequestProcessor().setWorkerThreadName(THREAD_NAME.get());        try {            // Parse and set Catalina and configuration specific            // request parameters            postParseSuccess = postParseRequest(req, request, res, response);            if (postParseSuccess) {                //check valves if we support async                request.setAsyncSupported(                        connector.getService().getContainer().getPipeline().isAsyncSupported());                // Calling the container                connector.getService().getContainer().getPipeline().getFirst().invoke(                        request, response); //责任链模式,调用处理管道            }...省略其他代码...    }

在CoyoteAdapter的service方法中

  • postParseRequest:生成request和response对象,其中会请求头信息匹配出相应的

  • connector.getService().getContainer().getPipeline().getFirst().invoke(request, response)会调用Service下的容器的管道,即从StandardEngine开始之后所有的所有容器,以责任链设计模式进行调用,具体参照第二章节的模块图。

org.apache.catalina.core.StandardWrapperValve
public final void invoke(Request request, Response response)        throws IOException, ServletException {...省略其他代码...                servlet = wrapper.allocate(); //生成servlet        try {            if ((servlet != null) && (filterChain != null)) {                // Swallow output if needed                if (context.getSwallowOutput()) {                    try {                        SystemLogHandler.startCapture();                        if (request.isAsyncDispatching()) {                            request.getAsyncContextInternal().doInternalDispatch();                        } else {                            filterChain.doFilter(request.getRequest(),                                    response.getResponse()); //调用filter,在filter结束后调用servlet                        }                    } finally {                        String log = SystemLogHandler.stopCapture();                        if (log != null && log.length() > 0) {                            context.getLogger().info(log);                        }                    }                } else {                    if (request.isAsyncDispatching()) {                        request.getAsyncContextInternal().doInternalDispatch();                    } else {                        filterChain.doFilter                            (request.getRequest(), response.getResponse());                    }                }            }        }...省略其他代码...

在管道最后的处理 StandardWrapperValve中,invoke方法会对匹配到的Servlet进行初始化和调用,其中servlet的调用会在过滤器链的最后进行调用

org.apache.catalina.core.ApplicationFilterChain
public void doFilter(ServletRequest request, ServletResponse response)        throws IOException, ServletException {        if( Globals.IS_SECURITY_ENABLED ) {            final ServletRequest req = request;            final ServletResponse res = response;            try {                java.security.AccessController.doPrivileged(                    new java.security.PrivilegedExceptionAction() {                        @Override                        public Void run()                            throws ServletException, IOException {                            internalDoFilter(req,res);                            return null;                        }                    }                );            } catch( PrivilegedActionException pe) {                Exception e = pe.getException();                if (e instanceof ServletException)                    throw (ServletException) e;                else if (e instanceof IOException)                    throw (IOException) e;                else if (e instanceof RuntimeException)                    throw (RuntimeException) e;                else                    throw new ServletException(e.getMessage(), e);            }        } else {            internalDoFilter(request,response);        }    }    private void internalDoFilter(ServletRequest request,                                  ServletResponse response)        throws IOException, ServletException {        // Call the next filter if there is one        if (pos < n) {            ApplicationFilterConfig filterConfig = filters[pos++];            try {                Filter filter = filterConfig.getFilter();                if (request.isAsyncSupported() && "false".equalsIgnoreCase(                        filterConfig.getFilterDef().getAsyncSupported())) {                    request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);                }                if( Globals.IS_SECURITY_ENABLED ) {                    final ServletRequest req = request;                    final ServletResponse res = response;                    Principal principal =                        ((HttpServletRequest) req).getUserPrincipal();                    Object[] args = new Object[]{req, res, this};                    SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);                } else {                    filter.doFilter(request, response, this);                }            } catch (IOException | ServletException | RuntimeException e) {                throw e;            } catch (Throwable e) {                e = ExceptionUtils.unwrapInvocationTargetException(e);                ExceptionUtils.handleThrowable(e);                throw new ServletException(sm.getString("filterChain.filter"), e);            }            return;        }        // We fell off the end of the chain -- call the servlet instance        try {            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {                lastServicedRequest.set(request);                lastServicedResponse.set(response);            }            if (request.isAsyncSupported() && !servletSupportsAsync) {                request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,                        Boolean.FALSE);            }            // Use potentially wrapped request from this point            if ((request instanceof HttpServletRequest) &&                    (response instanceof HttpServletResponse) &&                    Globals.IS_SECURITY_ENABLED ) {                final ServletRequest req = request;                final ServletResponse res = response;                Principal principal =                    ((HttpServletRequest) req).getUserPrincipal();                Object[] args = new Object[]{req, res};                SecurityUtil.doAsPrivilege("service",                                           servlet,                                           classTypeUsedInService,                                           args,                                           principal);            } else {                servlet.service(request, response);            }        } catch (IOException | ServletException | RuntimeException e) {            throw e;        } catch (Throwable e) {            e = ExceptionUtils.unwrapInvocationTargetException(e);            ExceptionUtils.handleThrowable(e);            throw new ServletException(sm.getString("filterChain.servlet"), e);        } finally {            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {                lastServicedRequest.set(null);                lastServicedResponse.set(null);            }        }    }

可以看到ApplicationFilterChain.doFilter方法中会递归过滤链,在调用完所有的filter之后,调用servlet.servce方法

javax.servlet.http.HttpServlet
protected void service(HttpServletRequest req, HttpServletResponse resp)        throws ServletException, IOException {        String method = req.getMethod();        if (method.equals(METHOD_GET)) {            long lastModified = getLastModified(req);            if (lastModified == -1) {                // servlet doesn't support if-modified-since, no reason                // to go through further expensive logic                doGet(req, resp);            } else {                long ifModifiedSince;                try {                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);                } catch (IllegalArgumentException iae) {                    // Invalid date header - proceed as if none was set                    ifModifiedSince = -1;                }                if (ifModifiedSince < (lastModified / 1000 * 1000)) {                    // If the servlet mod time is later, call doGet()                    // Round down to the nearest second for a proper compare                    // A ifModifiedSince of -1 will always be less                    maybeSetLastModified(resp, lastModified);                    doGet(req, resp);                } else {                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);                }            }        } else if (method.equals(METHOD_HEAD)) {            long lastModified = getLastModified(req);            maybeSetLastModified(resp, lastModified);            doHead(req, resp);        } else if (method.equals(METHOD_POST)) {            doPost(req, resp);        } else if (method.equals(METHOD_PUT)) {            doPut(req, resp);        } else if (method.equals(METHOD_DELETE)) {            doDelete(req, resp);        } else if (method.equals(METHOD_OPTIONS)) {            doOptions(req,resp);        } else if (method.equals(METHOD_TRACE)) {            doTrace(req,resp);        } else {            //            // Note that this means NO servlet supports whatever            // method was requested, anywhere on this server.            //            String errMsg = lStrings.getString("http.method_not_implemented");            Object[] errArgs = new Object[1];            errArgs[0] = method;            errMsg = MessageFormat.format(errMsg, errArgs);            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);        }    }

在HttpServlet中,service方法会根据请求的不同方法相应的调用doPost、doGet等方法。

时序图

感谢各位的阅读!关于"Tomcat9如何实现请求处理"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

方法 处理 线程 代码 管道 不同 容器 模式 端口 责任 队列 配置 信息 内容 对象 更多 篇文章 生成 监听 不错 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 上海喔噻互联网科技有限公司 河南云网互联网络科技有限公司 关于新基建和互联网科技 喔噻互联网科技 艾特科技互联网 润盈互联网科技 互联网科技宣传片 富国互联网科技创新基金 互联网实体化科技化 互联网汽车科技小镇 团飞科技与伯堂互联网服务平台 新兴科技互联网创新大赛颁奖典礼 恒生互联网科技指数跳水 广州市恰铎互联网科技有限公司 深圳育鹏互联网科技有限公司招聘 互联网科技人工智能实验室 上海钢联属于互联网科技股吗 上海互联网科技公司ppt 山东蛋芒互联网科技有限公司 平安好医生打造互联网科技医疗 亿人帮互联网科技有限公司 互联网科技公司经营范围 互联网科技公司起名 嘟嘟瓜互联网科技 广州恒生互联网科技有限 湖南诚度互联网科技有限公司 开一家科技互联网公司需要多少钱 中科明德北京互联网科技 上海钢联属于互联网科技股吗 杭州融税互联网科技有限公司
0