——每天的寥寥幾筆,堅持下去,將會是一份沉甸甸的積累。
今天的筆記是針對《how tomcat works》的第五章——servlet容器。。
該書的【源碼及書籍下載鏈接:http://pan.baidu.com/s/1ntBhXX3】
1.概念:一個連接httpConnector和serlvet的中間體,負責處理客戶請求、把請求傳送給Servlet並把結果返回給客戶。說白了,你把httpConnector那裏得到的request和response交給容器,容器能夠幫你找到對應的servlet,並把servlet的處理結果放到response中。
2.servlet容器有四種,engine、host、context、wrapper,從大到小,前者可以包含一個或多個後者。其中wrapper爲最小單位(不能再小了),只能負責一個servlet。
3.對於一個wrapper,有如下結構:
- 一個管道pipeline //類似一個過濾鏈
- 一個管道含有一個基閥和多個普通閥//一個基閥是必須有的,普通閥看情況添加。每個閥類似一個過濾器。
-----------------------------------------------------------
-simplePipeline 管道類
-SimpleWrapper servlet容器
-SimpleWrapperVavle基閥
-HeaderLoggerVavle普通閥
4.程序流程:
bootstrap類初始化,並啓動HTTPconnector;
httpConnector觸發servlet容器的invoke方法
HttpConnector connector = new HttpConnector();//新建連接器
Wrapper wrapper = new SimpleWrapper();
Valve valve1 = new HeaderLoggerValve();//新建普通閥
((Pipeline) wrapper).addValve(valve1);//容器添加普通閥,實際上是容器內管道添加閥。wrapper.addVavle()代碼:pipeline.addValve(valve);
connector.setContainer(wrapper);//這和tomcat分析二中一樣,設置容器,關聯連接器和servlet容器
connector.initialize();
connector.start();
基閥的初始化是在容器構造器中實現的
public SimpleWrapper() {
pipeline.setBasic(new SimpleWrapperValve());
}
->wrapper調用invoke方法
wrapper類:public void invoke(Request request, Response response)
throws IOException, ServletException {
pipeline.invoke(request, response);
}
->pipeline調用invoke方法
pipeline類:public void invoke(Request request, Response response)
throws IOException, ServletException {
(new SimplePipelineValveContext()).invokeNext(request, response);
}
->pipeline的內部類SimplePipelineValveContext調用invokeNext方法
public void invokeNext(Request request, Response response)
throws IOException, ServletException {
int subscript = stage;
stage = stage + 1;//表示第幾個閥
if (subscript < valves.length) {
valves[subscript].invoke(request, response, this);//閥又調用invoke方法
}
else if ((subscript == valves.length) && (basic != null)) {
basic.invoke(request, response, this);
}
else {
throw new ServletException("No valve");
}
}
從invoke到invokeNext又到invoke再到invokeNext,不斷把每個閥都遍歷到,最後調用基閥的invoke方法。
->調用基閥的invoke方法結束。
public void invoke(Request request, Response response, ValveContext valveContext)
throws IOException, ServletException {
SimpleWrapper wrapper = (SimpleWrapper) getContainer();
ServletRequest sreq = request.getRequest();
ServletResponse sres = response.getResponse();
Servlet servlet = null;
HttpServletRequest hreq = null;
if (sreq instanceof HttpServletRequest)
hreq = (HttpServletRequest) sreq;
HttpServletResponse hres = null;
if (sres instanceof HttpServletResponse)
hres = (HttpServletResponse) sres;
// Allocate a servlet instance to process this request
try {
servlet = wrapper.allocate();//*****************//
if (hres!=null && hreq!=null) {
servlet.service(hreq, hres);
}
else {
servlet.service(sreq, sres);
}
}
catch (ServletException e) {
}
}
--------------------------------------------------------------------end.
注意:不過上面還有一個地方值得說一下,最後一個invoke(也就是基閥的invoke)中//***//標註的那一句
servlet = wrapper.allocate();
servlet的實例化是在wrapper類的allocate方法中進行的。
servlet = (Servlet) classClass.newInstance();
servlet.init(null);//這裏可以進行相關init的處理
內容挺多,context容器就放在下一篇文章吧。