tomcat中servlet的工作機(jī)制
在研究servlet在tomcat中的工作機(jī)制前必須先看看servlet規(guī)范的一些重要的相關(guān)規(guī)定,規(guī)范提供了一個(gè)servlet接口,接口中包含的重要方法是init、service、destroy等方法,servlet在初始化時(shí)要調(diào)用init方法,在銷毀時(shí)要調(diào)用destroy方法,而對(duì)客戶端請(qǐng)求處理時(shí)則調(diào)用service方法。對(duì)于這些機(jī)制的支持都必須由tomcat內(nèi)部去支持,具體則是由wrapper容器提供支持。
在tomcat中消息流的流轉(zhuǎn)機(jī)制是通過四個(gè)不同級(jí)別的容器管道機(jī)制進(jìn)行流轉(zhuǎn)的,對(duì)于每個(gè)請(qǐng)求都是一層一層處理的。如下圖,當(dāng)客戶端請(qǐng)求到達(dá)服務(wù)端后請(qǐng)求被抽象成request對(duì)象后向四個(gè)容器進(jìn)行傳遞,首先經(jīng)過engine容器的管道通過若干閥門,最后通過standardenginevalve閥門流轉(zhuǎn)到host容器的管道,處理后繼續(xù)往下流轉(zhuǎn),通過standardhostvalve閥門流轉(zhuǎn)到context容器的管道,繼續(xù)往下流轉(zhuǎn),通過standardcontextvalve閥門流轉(zhuǎn)到wrapper容器的管道,而對(duì)servlet的核心處理也正是在standardwrappervalve閥門中。standardwrappervalve閥門調(diào)用servlet的service方法隊(duì)請(qǐng)求進(jìn)行處理,然后對(duì)客戶端響應(yīng)。
下面更深入了解下standardwrappervalve閥門調(diào)用servlet的過程。
web應(yīng)用的servlet類都是根據(jù)servlet接口,例如一般我們?cè)趯憳I(yè)務(wù)處理servlet類時(shí)都會(huì)繼承httpservlet類,為了遵循servlet規(guī)范,它其實(shí)最終也是實(shí)現(xiàn)了servlet接口,只是httpservlet定義了http協(xié)議的servlet,將協(xié)議共性的東西抽離出來復(fù)用。servlet處理客戶端請(qǐng)求的核心方法為service方法,所以對(duì)于httpservlet來說,它需要針對(duì)http協(xié)議的get、post、pu、delete、head、options、trace等請(qǐng)求方法做出不同的分發(fā)處理,為方便理解,下面用個(gè)簡(jiǎn)化的代碼展示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public abstract class httpservlet extends servlet{ public void service(servletrequest req, servletresponse res) throws servletexception, ioexception { httpservletrequest request = (httpservletrequest) req; httpservletresponse response = (httpservletresponse) res; string method = req.getmethod(); if (method.equals( "get" )) { doget(request, response); } else if (method.equals( "post" )) { dopost(request, response); } else if (method.equals( "head" )) { dohead(request, response); } } protected void dohead(httpservletrequest req, httpservletresponse resp) throws servletexception, ioexception{} protected void doget(httpservletrequest req, httpservletresponse resp) throws servletexception, ioexception{} protected void dopost(httpservletrequest req, httpservletresponse resp) throws servletexception, ioexception {} } |
service方法將請(qǐng)求對(duì)象和響應(yīng)對(duì)象轉(zhuǎn)換成httpservletrequest和httpservletresponse,然后獲取請(qǐng)求方法,根據(jù)請(qǐng)求方法調(diào)用不同的處理方法,例如如果為get方法則調(diào)用doget方法,那么在繼承了httpservlet類的servlet只需重寫doget或dopost方法完成業(yè)務(wù)邏輯處理,這就是我們熟悉的servlet了。
這樣一來,standardwrappervalve閥門調(diào)用servlet的工作其實(shí)就是通過反射機(jī)制實(shí)現(xiàn)對(duì)servlet對(duì)象的控制,例如在不配置load-on-startup情況下,客戶端首次訪問該servlet時(shí)由于還不存在該servlet對(duì)象,需要通過反射機(jī)制實(shí)例化出該servlet對(duì)象,并且調(diào)用初始化方法,所以這也是為什么第一次訪問某個(gè)servlet時(shí)會(huì)比較耗時(shí)的原因,后面客戶端再對(duì)該servlet訪問時(shí)都會(huì)使用該servlet對(duì)象,無需再做實(shí)例化和初始化操作。有了servlet對(duì)象后調(diào)用其service方法即完成了對(duì)客戶端請(qǐng)求的處理。
實(shí)際上通過反射機(jī)制實(shí)例化servlet對(duì)象是一個(gè)比較復(fù)雜的過程,它除了完成實(shí)例化和初始化工作外還要解析該servlet類包含的各種注解并作處理,另外,對(duì)于實(shí)現(xiàn)了singlethreadmodel接口的servlet類,它還要維護(hù)一個(gè)該servlet對(duì)象池。
綜上所述,servlet工作機(jī)制大致流程是:request -> standardenginevalve -> standardhostvalve -> standardcontextvalve -> standardwrappervalve -> 實(shí)例化并初始化servlet對(duì)象 -> 調(diào)用該servlet對(duì)象的service方法 -> response。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
原文鏈接:http://blog.csdn.net/wangyangzhizhou/article/details/52273676