tomcat中servlet的工作機制
在研究servlet在tomcat中的工作機制前必須先看看servlet規范的一些重要的相關規定,規范提供了一個servlet接口,接口中包含的重要方法是init、service、destroy等方法,servlet在初始化時要調用init方法,在銷毀時要調用destroy方法,而對客戶端請求處理時則調用service方法。對于這些機制的支持都必須由tomcat內部去支持,具體則是由wrapper容器提供支持。
在tomcat中消息流的流轉機制是通過四個不同級別的容器管道機制進行流轉的,對于每個請求都是一層一層處理的。如下圖,當客戶端請求到達服務端后請求被抽象成request對象后向四個容器進行傳遞,首先經過engine容器的管道通過若干閥門,最后通過standardenginevalve閥門流轉到host容器的管道,處理后繼續往下流轉,通過standardhostvalve閥門流轉到context容器的管道,繼續往下流轉,通過standardcontextvalve閥門流轉到wrapper容器的管道,而對servlet的核心處理也正是在standardwrappervalve閥門中。standardwrappervalve閥門調用servlet的service方法隊請求進行處理,然后對客戶端響應。
下面更深入了解下standardwrappervalve閥門調用servlet的過程。
web應用的servlet類都是根據servlet接口,例如一般我們在寫業務處理servlet類時都會繼承httpservlet類,為了遵循servlet規范,它其實最終也是實現了servlet接口,只是httpservlet定義了http協議的servlet,將協議共性的東西抽離出來復用。servlet處理客戶端請求的核心方法為service方法,所以對于httpservlet來說,它需要針對http協議的get、post、pu、delete、head、options、trace等請求方法做出不同的分發處理,為方便理解,下面用個簡化的代碼展示:
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方法將請求對象和響應對象轉換成httpservletrequest和httpservletresponse,然后獲取請求方法,根據請求方法調用不同的處理方法,例如如果為get方法則調用doget方法,那么在繼承了httpservlet類的servlet只需重寫doget或dopost方法完成業務邏輯處理,這就是我們熟悉的servlet了。
這樣一來,standardwrappervalve閥門調用servlet的工作其實就是通過反射機制實現對servlet對象的控制,例如在不配置load-on-startup情況下,客戶端首次訪問該servlet時由于還不存在該servlet對象,需要通過反射機制實例化出該servlet對象,并且調用初始化方法,所以這也是為什么第一次訪問某個servlet時會比較耗時的原因,后面客戶端再對該servlet訪問時都會使用該servlet對象,無需再做實例化和初始化操作。有了servlet對象后調用其service方法即完成了對客戶端請求的處理。
實際上通過反射機制實例化servlet對象是一個比較復雜的過程,它除了完成實例化和初始化工作外還要解析該servlet類包含的各種注解并作處理,另外,對于實現了singlethreadmodel接口的servlet類,它還要維護一個該servlet對象池。
綜上所述,servlet工作機制大致流程是:request -> standardenginevalve -> standardhostvalve -> standardcontextvalve -> standardwrappervalve -> 實例化并初始化servlet對象 -> 調用該servlet對象的service方法 -> response。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
原文鏈接:http://blog.csdn.net/wangyangzhizhou/article/details/52273676