服务器之家:专注于服务器技术及软件下载分享
分类导航

云服务器|WEB服务器|FTP服务器|邮件服务器|虚拟主机|服务器安全|DNS服务器|服务器知识|Nginx|IIS|Tomcat|

服务器之家 - 服务器技术 - Tomcat - Tomcat源码解析之Web请求与处理

Tomcat源码解析之Web请求与处理

2021-09-24 16:08Turbo码先生 Tomcat

这篇文章主要介绍了Tomcat源码解析之Web请求与处理,文中有非常详细的代码示例,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下

前言

tomcat最全uml类图

Tomcat源码解析之Web请求与处理

tomcat请求处理过程:

Tomcat源码解析之Web请求与处理

connector对象创建的时候,会创建http11nioprotocol的protocolhandler,在connector的startinteral方法中,会启动abstractprotocol,abstractprotocol启动nioendpoint进行监听客户端的请求,endpoint接受到客户端的请求之后,会交给container去处理请求。请求从engine开始经过的所有容器都含有责任链模式,每经过一个容器都会调用该容器的责任链对请求进行处理。

Tomcat源码解析之Web请求与处理

一、endpoint

Tomcat源码解析之Web请求与处理

默认的endpoint实现是nioendpoint,nioendpoint有四个内部类,分别是poller、acceptor、pollerevent、socketprocessor、niosocketwrapper。

(1)acceptor负责监听用户的请求,监听到用户请求之后,调用getpoller0().register(channel);先将当前请求封装成pollerevent,new pollerevent(socket, ka, op_register); 将当前请求,封装成注册事件,并添加到pollerevent队列中,然后将pollerevent注册到poller的selector对象上面。

(2)poller线程会一直遍历可以处理的事件(netty的selestor),当找到需要处理的事件之后,调用processkey(sk, socketwrapper);对,执行要处理的pollerevent的run方法,对请求进行处理。

(3)pollerevent继承自runnable接口,在其run方法里面,如果是pollerevent的事件是注册op_register,那么就将当前的socket注册到poller的selector上。

?
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
public void run() {
           if (interestops == op_register) {
               try {
                   // 核心代码,终于找到了!!!!!
                   // 当事件是注册的时候,将当前的niosocketchannel注册到poller的selector上。
                   socket.getiochannel().register(
                           socket.getpoller().getselector(), selectionkey.op_read, socketwrapper);
               } catch (exception x) {
                   log.error(sm.getstring("endpoint.nio.registerfail"), x);
               }
           } else {
               final selectionkey key = socket.getiochannel().keyfor(socket.getpoller().getselector());
               try {
                   if (key == null) {
 
                       // the key was cancelled (e.g. due to socket closure)
                       // and removed from the selector while it was being
                       // processed. count down the connections at this point
                       // since it won't have been counted down when the socket
                       // closed.
                       // selectionkey被取消的时候需要将selectionkey对应的endpoint的connection计数器,减一
                       socket.socketwrapper.getendpoint().countdownconnection();
                       ((niosocketwrapper) socket.socketwrapper).closed = true;
                   } else {
                       final niosocketwrapper socketwrapper = (niosocketwrapper) key.attachment();
                       if (socketwrapper != null) {
                           //we are registering the key to start with, reset the fairness counter.
                           int ops = key.interestops() | interestops;
                           socketwrapper.interestops(ops);
                           key.interestops(ops);
                       } else {
                           socket.getpoller().cancelledkey(key);
                       }
                   }
               } catch (cancelledkeyexception ckx) {
                   try {
                       socket.getpoller().cancelledkey(key);
                   } catch (exception ignore) {
                   }
               }
           }
       }

(4)poller线程内会执行keycount = selector.select(selectortimeout);获取当前需要处理的selectionkey的数量,然后当keycount大于0时,会获取selector的迭代器,遍历所有需要的selectionkey,并对其进行处理。在这里将socket的事件封装成niosocketwrapper。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 得到selectedkeys的迭代器
iterator<selectionkey> iterator =
         keycount > 0 ? selector.selectedkeys().iterator() : null;
 
 // 遍历所有的selectionkey,并对其进行处理
 while (iterator != null && iterator.hasnext()) {
     selectionkey sk = iterator.next();
     iterator.remove();
     niosocketwrapper socketwrapper = (niosocketwrapper) sk.attachment();
     // attachment may be null if another thread has called
     // cancelledkey()
     // 如果有attachment,就处理
     if (socketwrapper != null) {
         // 处理事件
         processkey(sk, socketwrapper);
     }
 }

processkey在处理selectionkey,如果当前poller已经关闭,就取消key。selectionkey对应的channel如果发生读事件,就调用abatractendpoint.processsocket执行读操作processsocket(attachment, socketevent.open_read, true),如果selectionkey对应的channel发生写事件,就执行processsocket(attachment, socketevent.open_write, true);读大于写。socket的事件处理调用的是abatractendpoint的processsocket方法。

?
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
protected void processkey(selectionkey sk, niosocketwrapper attachment) {
         try {
             if (close) {
                 // 如果poller已经关闭了,就取消key
                 cancelledkey(sk);
             } else if (sk.isvalid() && attachment != null) {
                 if (sk.isreadable() || sk.iswritable()) {
                     if (attachment.getsendfiledata() != null) {
                         processsendfile(sk, attachment, false);
                     } else {
                         unreg(sk, attachment, sk.readyops());
                         boolean closesocket = false;
                         // read goes before write
                         // 读优于写
                         // 如果selectionkey对应的channel已经准备好了读
                         // 就对niosocketwrapper进行读操作
                         if (sk.isreadable()) {
                             if (!processsocket(attachment, socketevent.open_read, true)) {
                                 closesocket = true;
                             }
                         }
                         // 如果selectionkey对应的channel已经准备好了写
                         // 就对niosocketwrapper进行写操作
                         if (!closesocket && sk.iswritable()) {
                             if (!processsocket(attachment, socketevent.open_write, true)) {
                                 closesocket = true;
                             }
                         }
                         if (closesocket) {
                             // 如果已经关闭了,就取消key
                             cancelledkey(sk);
                         }
                     }
                 }
                 
}

abatractendpoint.processsocket方法首先从缓存中获取socketprocessor类,如果缓存中没有就创建一个,socketprocessorbase接口对应的就是nioendpoint.socketprocessor,也就是worker。将对应的socketprocessor类放入到线程池中执行。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public boolean processsocket(socketwrapperbase<s> socketwrapper,
                                socketevent event, boolean dispatch) {
 
   // 得到socket的处理器
   // connector在构造函数里面已经指定了协议:org.apache.coyote.http11.http11nioprotocol。
   socketprocessorbase<s> sc = processorcache.pop();
   if (sc == null) {
   // 如果没有,就创建一个socket的处理器。创建的时候指定socketwrapper以及socket的事件。
       sc = createsocketprocessor(socketwrapper, event);
   } else {
       sc.reset(socketwrapper, event);
   }
   //socket的处理交给了线程池去处理。
   executor executor = getexecutor();
   if (dispatch && executor != null) {
       executor.execute(sc);
   } else {
       sc.run();
   }

(5)nioendpoint.niosocketwrapper,是socket的封装类,增强类,将socket与其他对象建立关联。

?
1
2
3
4
5
6
7
8
9
10
11
public static class niosocketwrapper extends socketwrapperbase<niochannel> {
       private final nioselectorpool pool;
 
       private poller poller = null; // 轮询的poller
       private int interestops = 0;
       private countdownlatch readlatch = null;
       private countdownlatch writelatch = null;
       private volatile sendfiledata sendfiledata = null;
       private volatile long lastread = system.currenttimemillis();
       private volatile long lastwrite = lastread;
       private volatile boolean closed = false;

(6)nioendpoint.socketprocessor(worker)继承了runnable接口,负责对socket的g各种事件进行处理。读事件、写事件、停止时间、超时事件、断连事件、错误时间、连接失败事件。

Tomcat源码解析之Web请求与处理

socketprocessor的dorun方法,会根据socketstate进行处理,socketstate 为stop、disconnect或者error的时候就进行关闭,socketwrapperbase对应的selector事件,得到指定的handler处理器进行处理。

?
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
@override
 protected void dorun() {
     niochannel socket = socketwrapper.getsocket();
     selectionkey key = socket.getiochannel().keyfor(socket.getpoller().getselector());
 
     try {
         int handshake = -1;
 
         try {
             if (key != null) {
                 if (socket.ishandshakecomplete()) {
                     // 是否已经握手成功,不需要tls(加密)握手,就让处理器对socket和event的组合进行处理。
                     handshake = 0;
                 } else if (event == socketevent.stop || event == socketevent.disconnect ||
                         event == socketevent.error) {
                     // 不能够完成tls握手,就把他认为是tls握手失败。
                     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.
                     // 握手从/向socket读/写时,握手一旦完成状态应该为open_write,
                     // 握手是在套接字打开时发生的,因此在完成后状态必须始终为open_read
                     // 始终设置此选项是可以的,因为它仅在握手完成时使用。
                     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) {
                 // 调用处理器进行处理。
                 // nioendpoint的默认handler是http11的
                 // 这里的handler是abstractprotocol.connectionhandler
                 // 这个handler的设置方法是:
                 // 首先在connector类的构造函数中,将默认的protocolhandler设置为org.apache.coyote.http11.http11nioprotocol
                 // abstracthttp11protocol的构造函数里面创建了handler类connectionhandler
                 state = gethandler().process(socketwrapper, socketevent.open_read);
             } else {
                 state = gethandler().process(socketwrapper, event);
             }
             // 如果返回的状态是socketstate,那么就关掉连接
             if (state == socketstate.closed) {
                 close(socket, key);
             }
         } else if (handshake == -1) {
             gethandler().process(socketwrapper, socketevent.connect_fail);
             close(socket, key);
         } else if (handshake == selectionkey.op_read) {
             // 如果是selectionkey.op_read,也就是读事件的话,就将op_read时间设置到socketwrapper
             socketwrapper.registerreadinterest();
         } else if (handshake == selectionkey.op_write) {
             // 如果是selectionkey.op_write,也就是读事件的话,就将op_write事件设置到socketwrapper
             socketwrapper.registerwriteinterest();
         }

二、connectionhandler

Tomcat源码解析之Web请求与处理

(1)connectionhandler用于根据socket连接找到相应的engine处理器。

上面是socketprocessor的dorun方法,执行了gethandler().process(socketwrapper, socketevent.open_read);;process方法是首先在map缓存中查找当前socket是否存在对应的processor,如果不存在,再去可循环的处理器栈中查找是否存在,如果不存在就创建相应的processor,然后将新创建的processor与socket建立映射,存在connection的map中。在任何一个阶段得到processor对象之后,会执行processor的process方法state = processor.process(wrapper, status);

?
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
protected static class connectionhandler<s> implements abstractendpoint.handler<s> {
 
        private final abstractprotocol<s> proto;
        private final requestgroupinfo global = new requestgroupinfo();
        private final atomiclong registercount = new atomiclong(0);
        // 终于找到了这个集合,给socket和处理器建立连接
        // 对每个有效链接都会缓存进这里,用于连接选择一个合适的processor实现以进行请求处理。
        private final map<s, processor> connections = new concurrenthashmap<>();
        // 可循环的处理器栈
        private final recycledprocessors recycledprocessors = new recycledprocessors(this);
 
        
        @override
        public socketstate process(socketwrapperbase<s> wrapper, socketevent status) {
            if (getlog().isdebugenabled()) {
                getlog().debug(sm.getstring("abstractconnectionhandler.process",
                        wrapper.getsocket(), status));
            }
            if (wrapper == null) {
                // wrapper == null 表示socket已经被关闭了,所以不需要做任何操作。
                return socketstate.closed;
            }
            // 得到wrapper内的socket对象
            s socket = wrapper.getsocket();
            // 从map缓冲区中得到socket对应的处理器。
            processor processor = connections.get(socket);
            if (getlog().isdebugenabled()) {
                getlog().debug(sm.getstring("abstractconnectionhandler.connectionsget",
                        processor, socket));
            }
 
            // timeouts are calculated on a dedicated thread and then
            // dispatched. because of delays in the dispatch process, the
            // timeout may no longer be required. check here and avoid
            // unnecessary processing.
 
            // 超时是在专用线程上计算的,然后被调度。
            // 因为调度过程中的延迟,可能不再需要超时。检查这里,避免不必要的处理。
            if (socketevent.timeout == status &&
                    (processor == null ||
                            !processor.isasync() && !processor.isupgrade() ||
                            processor.isasync() && !processor.checkasynctimeoutgeneration())) {
                // this is effectively a no-op
                return socketstate.open;
            }
            // 如果map缓存存在该socket相关的处理器
            if (processor != null) {
                // make sure an async timeout doesn't fire
                // 确保没有触发异步超时
                getprotocol().removewaitingprocessor(processor);
            } else if (status == socketevent.disconnect || status == socketevent.error) {
                // nothing to do. endpoint requested a close and there is no
                // longer a processor associated with this socket.
                // socketevent事件是关闭,或者socketevent时间出错,此时不需要做任何操作。
                // endpoint需要一个closed的信号,并且这里不再有与这个socket有关联了
                return socketstate.closed;
            }
 
            containerthreadmarker.set();
 
            try {
                // map缓存不存在该socket相关的处理器
                if (processor == null) {
                    string negotiatedprotocol = wrapper.getnegotiatedprotocol();
                    // openssl typically returns null whereas jsse typically
                    // returns "" when no protocol is negotiated
                    // openssl通常返回null,而jsse通常在没有协议协商时返回""
                    if (negotiatedprotocol != null && negotiatedprotocol.length() > 0) {
                        // 获取协商协议
                        upgradeprotocol upgradeprotocol = getprotocol().getnegotiatedprotocol(negotiatedprotocol);
                        if (upgradeprotocol != null) {
                            // 升级协议为空
                            processor = upgradeprotocol.getprocessor(wrapper, getprotocol().getadapter());
                            if (getlog().isdebugenabled()) {
                                getlog().debug(sm.getstring("abstractconnectionhandler.processorcreate", processor));
                            }
                        } else if (negotiatedprotocol.equals("http/1.1")) {
                            // explicitly negotiated the default protocol.
                            // obtain a processor below.
                        } else {
                            // todo:
                            // openssl 1.0.2's alpn callback doesn't support
                            // failing the handshake with an error if no
                            // protocol can be negotiated. therefore, we need to
                            // fail the connection here. once this is fixed,
                            // replace the code below with the commented out
                            // block.
                            if (getlog().isdebugenabled()) {
                                getlog().debug(sm.getstring("abstractconnectionhandler.negotiatedprocessor.fail",
                                        negotiatedprotocol));
                            }
                            return socketstate.closed;
                            /*
                             * to replace the code above once openssl 1.1.0 is
                             * used.
                            // failed to create processor. this is a bug.
                            throw new illegalstateexception(sm.getstring(
                                    "abstractconnectionhandler.negotiatedprocessor.fail",
                                    negotiatedprotocol));
                            */
                        }
                    }
                }
                // 经过上面的操作,processor还是null的话。
                if (processor == null) {
                    // 从recycledprocessors可循环processors中获取processor
                    processor = recycledprocessors.pop();
                    if (getlog().isdebugenabled()) {
                        getlog().debug(sm.getstring("abstractconnectionhandler.processorpop", processor));
                    }
                }
                if (processor == null) {
                    // 创建处理器
                    processor = getprotocol().createprocessor();
                    register(processor);
                    if (getlog().isdebugenabled()) {
                        getlog().debug(sm.getstring("abstractconnectionhandler.processorcreate", processor));
                    }
                }
                processor.setsslsupport(
                        wrapper.getsslsupport(getprotocol().getclientcertprovider()));
 
                // 将socket和processor建立关联。
                connections.put(socket, processor);
 
                socketstate state = socketstate.closed;
                do {
                    // 调用processor的process方法。
                    state = processor.process(wrapper, status);
 
                    // processor的process方法返回升级状态
                    if (state == socketstate.upgrading) {
                        // get the http upgrade handler
                        // 得到http的升级句柄
                        upgradetoken upgradetoken = processor.getupgradetoken();
                        // retrieve leftover input
                        // 检索剩余输入
                        bytebuffer leftoverinput = processor.getleftoverinput();
                        if (upgradetoken == null) {
                            // assume direct http/2 connection
                            upgradeprotocol upgradeprotocol = getprotocol().getupgradeprotocol("h2c");
                            if (upgradeprotocol != null) {
                                // release the http11 processor to be re-used
                                release(processor);
                                // create the upgrade processor
                                processor = upgradeprotocol.getprocessor(wrapper, getprotocol().getadapter());
                                wrapper.unread(leftoverinput);
                                // associate with the processor with the connection
                                connections.put(socket, processor);
                            } else {
                                if (getlog().isdebugenabled()) {
                                    getlog().debug(sm.getstring(
                                            "abstractconnectionhandler.negotiatedprocessor.fail",
                                            "h2c"));
                                }
                                // exit loop and trigger appropriate clean-up
                                state = socketstate.closed;
                            }
                        } else {
                            httpupgradehandler httpupgradehandler = upgradetoken.gethttpupgradehandler();
                            // release the http11 processor to be re-used
                            release(processor);
                            // create the upgrade processor
                            processor = getprotocol().createupgradeprocessor(wrapper, upgradetoken);
                            if (getlog().isdebugenabled()) {
                                getlog().debug(sm.getstring("abstractconnectionhandler.upgradecreate",
                                        processor, wrapper));
                            }
                            wrapper.unread(leftoverinput);
                            // associate with the processor with the connection
                            connections.put(socket, processor);
                            // initialise the upgrade handler (which may trigger
                            // some io using the new protocol which is why the lines
                            // above are necessary)
                            // this cast should be safe. if it fails the error
                            // handling for the surrounding try/catch will deal with
                            // it.
                            if (upgradetoken.getinstancemanager() == null) {
                                httpupgradehandler.init((webconnection) processor);
                            } else {
                                classloader oldcl = upgradetoken.getcontextbind().bind(false, null);
                                try {
                                    httpupgradehandler.init((webconnection) processor);
                                } finally {
                                    upgradetoken.getcontextbind().unbind(false, oldcl);
                                }
                            }
                        }
                    }
                } while (state == socketstate.upgrading);  

(2)以http11协议为例,执行的是http11processor,http11processor的祖父类abstractprocessorlight实现了process方法,process调用了service模板方法,service模板方法是由http11processor进行实现的。service方法最重要的操作是执行getadapter().service(request, response);

?
1
2
3
4
5
6
7
@override
    public socketstate service(socketwrapperbase<?> socketwrapper)
            throws ioexception {
        // 上面省略n行
        // 调用coyote的service方法
         getadapter().service(request, response);
         // 下面省略n行

三、coyote

回顾一下coyoteadapter的创建是在connector的initinternal方法。

?
1
2
3
4
5
6
7
@override
    public socketstate service(socketwrapperbase<?> socketwrapper)
            throws ioexception {
        // 上面省略n行
        // 调用coyote的service方法
         getadapter().service(request, response);
         // 下面省略n行

coyote的作用就是coyote.request和coyote.rsponse转成httpservletrequest和httpservletrsponse。然后,因为connector在init的时候,将自己注入到了coyoteadapter中,所以,直接通过connector.getservice()方法就可以拿到service,然后从service开始调用责任链模式,进行处理。

?
1
2
3
4
5
6
7
@override
    public socketstate service(socketwrapperbase<?> socketwrapper)
            throws ioexception {
        // 上面省略n行
        // 调用coyote的service方法
         getadapter().service(request, response);
         // 下面省略n行

四、容器责任链模式

接下来就是从standradengine开始的责任链模式。首先执行standradengine的责任链模式,找到合适的engine,合适的engine在通过责任链模式找到合适的context,直到找到standardwrappervalve。最后执行到standardwrappervalve的invoke方法。首先查看context和wrapper是不是不可用了,如果可用,并且servelt还没有被初始化,就执行初始化操作。如果是单线程模式就直接返回之前创建好的servelt,如果是多线程模式,就先创建一个servelt对象进行返回。

?
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
@override
    public final void invoke(request request, response response)
            throws ioexception, servletexception {
        // 初始化我们需要的本地变量
        boolean unavailable = false;
        throwable throwable = null;
        // this should be a request attribute...
        long t1 = system.currenttimemillis();
        // 原子类atomicinteger,cas操作,表示请求的数量。
        requestcount.incrementandget();
        standardwrapper wrapper = (standardwrapper) getcontainer();
        servlet servlet = null;
        context context = (context) wrapper.getparent();
 
        // 检查当前的context应用是否已经被标注为不可以使用
        if (!context.getstate().isavailable()) {
            // 如果当前应用不可以使用的话,就报503错误。
            response.senderror(httpservletresponse.sc_service_unavailable,
                    sm.getstring("standardcontext.isunavailable"));
            unavailable = true;
        }
 
        // 检查servelt是否被标记为不可使用
        if (!unavailable && wrapper.isunavailable()) {
            container.getlogger().info(sm.getstring("standardwrapper.isunavailable",
                    wrapper.getname()));
            long available = wrapper.getavailable();
            if ((available > 0l) && (available < long.max_value)) {
                response.setdateheader("retry-after", available);
                response.senderror(httpservletresponse.sc_service_unavailable,
                        sm.getstring("standardwrapper.isunavailable",
                                wrapper.getname()));
            } else if (available == long.max_value) {
                response.senderror(httpservletresponse.sc_not_found,
                        sm.getstring("standardwrapper.notfound",
                                wrapper.getname()));
            }
            unavailable = true;
        }
        // servelt是第一次调用的时候初始化
        try {
            if (!unavailable) {
                // 如果此时servelt还没有被初始化,就分配一个servelt实例来处理request请求。
                servlet = wrapper.allocate();
            }
        /// 省略代码..........................................
        // // 给该request创建filter过滤链。filter过滤链执行完之后,会执行servelt
        applicationfilterchain filterchain =
                applicationfilterfactory.createfilterchain(request, wrapper, servlet);
 
        // call the filter chain for this request
        // note: this also calls the servlet's service() method
        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());
                        }
        /// 省略代码..........................................
       

到此这篇关于tomcat源码解析之web请求与处理的文章就介绍到这了,更多相关tomcat的web请求与处理内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_34037358/article/details/115579034

延伸 · 阅读

精彩推荐
  • TomcatEclipse创建tomcat实现过程原理详解

    Eclipse创建tomcat实现过程原理详解

    这篇文章主要介绍了Eclipse创建tomcat实现过程原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以...

    海绵般汲取11642021-09-16
  • TomcatTomcat整体结构简单介绍

    Tomcat整体结构简单介绍

    这篇文章主要介绍了Tomcat整体结构简单介绍,Tomcat的本质是一个Servlet容器。一个Servlet能做的事情是:处理请求资源,并为客户端填充response对象,需要的朋友...

    叫我田露也行12302021-09-07
  • TomcatTomcat CentOS安装实现过程图解

    Tomcat CentOS安装实现过程图解

    这篇文章主要介绍了Tomcat CentOS安装实现过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考...

    agrin5842021-09-15
  • Tomcat如何查看tomcat的控制台输出的方法

    如何查看tomcat的控制台输出的方法

    这篇文章主要介绍了如何查看tomcat的控制台输出的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    CaiCaiNeo11932021-08-29
  • Tomcat解决Tomcat的maxPostSize属性的配置需要注意的问题

    解决Tomcat的maxPostSize属性的配置需要注意的问题

    这篇文章主要介绍了解决Tomcat的maxPostSize属性的配置需要注意的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋...

    life is wonderful12012021-09-13
  • Tomcat一次tomcat源码启动控制台中文乱码的调试过程记录

    一次tomcat源码启动控制台中文乱码的调试过程记录

    平时在使用tomcat做一些服务的时候经常遇到各种乱码问题,下面这篇文章主要给大家介绍了一次tomcat源码启动控制台中文乱码的调试过程,需要的朋友可以...

    zhoutaoping199211852021-09-24
  • TomcatTomcat安装配置方法图文教程

    Tomcat安装配置方法图文教程

    这篇文章主要为大家详细介绍了Tomcat安装配置方法图文教程,java环境变量如何配置,Eclipse安装配置方法图文教程 ,为大家分享了三个教程,感兴趣的小伙...

    Tomcat教程网13292021-08-11
  • TomcatTomcat服务器的安全设置

    Tomcat服务器的安全设置

    tomcat是一个开源Web服务器,基于Tomcat的Web运行效率高,可以在一般的硬件平台上流畅运行,因此,颇受Web站长的青睐。不过,在默认配置下其存在一定的安...

    IT专家网9002021-08-03