黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

Tomcat源碼分析(三)--連接器是如何與容器關(guān)聯(lián)的

系統(tǒng) 2299 0
本系列轉(zhuǎn)載自?http://blog.csdn.net/haitao111313/article/category/1179996?

這篇文章要弄懂一個(gè)問(wèn)題,我們知道,一個(gè)鏈接器是跟一個(gè)容器關(guān)聯(lián)的, 容器跟鏈接器是在什么時(shí)候關(guān)聯(lián)上的?

  在明白這個(gè)問(wèn)題前要先了解一下Digester庫(kù),這個(gè)庫(kù)簡(jiǎn)單的說(shuō)就是解析xml文件,這里有兩個(gè)概念:模式和規(guī)則,所謂模式就是一個(gè)xml的標(biāo)簽,規(guī)則就是遇到一個(gè)xml標(biāo)簽需要做什么,看一下他主要的三個(gè)方法:

? ? ? 1:addObjectCreate(String pattern, String className, String attributeName) ? ?根據(jù)模式pattern實(shí)例化一個(gè)對(duì)象className

? ? ? 2:addSetProperties(String pattern) ? 設(shè)置這個(gè)模式的屬性

? ? ? 3:addSetNext(String pattern, String methodName, String paramType) ?添加模式之間的關(guān)系,調(diào)用父模式的

? ? 上面可能不好理解,看tomcat是怎么用到Digester的,在org.apache.catalina.startup.Catalina.createStartDigester()的方法里(這個(gè)方法是在服務(wù)組件啟動(dòng)的時(shí)候調(diào)用的,詳細(xì)參考 Tomcat源碼分析(一)--服務(wù)啟動(dòng) ),在這個(gè)方法里有使用Digester來(lái)解析server.xml文件:

? ??

  1. digester.addObjectCreate( "Server/Service" ,??
  2. ???????????????????????????????? "org.apache.catalina.core.StandardService" ,??
  3. ???????????????????????????????? "className" ); //?添加一個(gè)模式“Server/Service”,當(dāng)在xml文件(這里是server.xml)里遇到“Server”標(biāo)簽下的Service標(biāo)簽的時(shí)候,根據(jù)標(biāo)簽Service的屬性“className”為類名實(shí)例化一個(gè)對(duì)象,默認(rèn)類名是"org.apache.catalina.core.StandardServer" ??
  4. ???????digester.addSetProperties( "Server/Service" );? //設(shè)置對(duì)象StandardService的屬性,有些什么屬性由xml里的Service標(biāo)簽指定 ??
  5. ???????digester.addSetNext( "Server/Service" ,??
  6. ??????????????????????????? "addService" ,??
  7. ??????????????????????????? "org.apache.catalina.Service" ); //調(diào)用Service標(biāo)簽的上一級(jí)標(biāo)簽Server的對(duì)象(即StandardServer)的addService方法,把Service添加進(jìn)Server,設(shè)置它們的關(guān)系,最后一個(gè)參數(shù)表示addService方法的參數(shù)類型 ??
這樣StandardServer和StandardService便有了所屬關(guān)系,現(xiàn)在看容器跟鏈接器是怎么連接的,再看createStartDigester方法:

  1. digester.addObjectCreate( "Server/Service/Connector" ,??
  2. ????????????????????????????????? "org.apache.catalina.connector.http.HttpConnector" ,??
  3. ????????????????????????????????? "className" );??
  4. ????????digester.addSetProperties( "Server/Service/Connector" );??
  5. ????????digester.addSetNext( "Server/Service/Connector" ,??
  6. ???????????????????????????? "addConnector" ,??
  7. ???????????????????????????? "org.apache.catalina.Connector" );??

這里很好理解,跟上面的是一樣的,遇到標(biāo)簽Server/Service/Connector的時(shí)候(這里簡(jiǎn)化了說(shuō)法,應(yīng)該是標(biāo)簽Server下的子標(biāo)簽Service的子標(biāo)簽Connector,有點(diǎn)拗口),實(shí)例化HttpConnector,然后在它的上一級(jí)父容器StandardService下調(diào)用addConnector,這樣就把鏈接器HttpConnector添加進(jìn)容器StandardService下了,看StandardService的addConnector方法:

  1. public ? void ?addConnector(Connector?connector)?{??
  2. ????? synchronized ?(connectors)?{??
  3. ?????????connector.setContainer( this .container);? //本來(lái)這里就應(yīng)該把容器和連接器關(guān)聯(lián)上的,但是在一開(kāi)始tomcat啟動(dòng)的時(shí)候,Digester是先添加鏈接器,所以容器container還是為null的,但是沒(méi)有關(guān)系,后面還會(huì)另一個(gè)地方關(guān)聯(lián)他們,這里應(yīng)該牢記的是容器和連接器都是在Service里面 ??
  4. ?????????connector.setService( this );??
  5. ?????????Connector?results[]?=? new ?Connector[connectors.length?+? 1 ];??
  6. ?????????System.arraycopy(connectors,? 0 ,?results,? 0 ,?connectors.length);??
  7. ?????????results[connectors.length]?=?connector;??
  8. ?????????connectors?=?results;??
  9. ??
  10. ????????? if ?(initialized)?{??
  11. ????????????? try ?{??
  12. ?????????????????connector.initialize();??
  13. ?????????????}? catch ?(LifecycleException?e)?{??
  14. ?????????????????e.printStackTrace(System.err);??
  15. ?????????????}??
  16. ?????????}??
  17. ??
  18. ????????? if ?(started?&&?(connector? instanceof ?Lifecycle))?{??
  19. ????????????? try ?{??
  20. ?????????????????((Lifecycle)?connector).start();??
  21. ?????????????}? catch ?(LifecycleException?e)?{??
  22. ?????????????????;??
  23. ?????????????}??
  24. ?????????}??
  25. ??
  26. ????????? //?Report?this?property?change?to?interested?listeners ??
  27. ?????????support.firePropertyChange( "connector" ,? null ,?connector);??
  28. ?????}??
  29. ??
  30. ?}??
這個(gè)方法很簡(jiǎn)單,就是把一個(gè)鏈接器connector添加到StandardService的connectors數(shù)組里,然后關(guān)聯(lián)上StandardService的容器。代碼上也做了一點(diǎn)說(shuō)明(很重要)。連接器添加進(jìn)StandardService了,現(xiàn)在看容器是什么時(shí)候添加進(jìn)StandardService的,其實(shí)方法是一樣的,再回到createStartDigester方法:

  1. digester.addRuleSet( new ?EngineRuleSet( "Server/Service/" )); //這句代碼是在createStartDigester方法里面 ??
  2. --------------------------》下面進(jìn)入EngineRuleSet類的addRuleInstances方法??
  3. public ? void ?addRuleInstances(Digester?digester)?{??
  4. ???????digester.addObjectCreate(prefix?+? "Engine" ,??
  5. ???????????????????????????????? "org.apache.catalina.core.StandardEngine" ,??
  6. ???????????????????????????????? "className" );??
  7. ???????digester.addSetProperties(prefix?+? "Engine" );??
  8. ???????digester.addRule(prefix?+? "Engine" ,??
  9. ???????????????????????? new ?LifecycleListenerRule??
  10. ????????????????????????(digester,??
  11. ????????????????????????? "org.apache.catalina.startup.EngineConfig" ,??
  12. ????????????????????????? "engineConfigClass" ));??
  13. ???????digester.addSetNext(prefix?+? "Engine" ,??
  14. ??????????????????????????? "setContainer" ,??
  15. ??????????????????????????? "org.apache.catalina.Container" );? //這里調(diào)用StandardService的方法setContainer方法,把容器添加進(jìn)StandardService里面 ??
先不去糾結(jié)Digester是怎么進(jìn)入addRuleInstances方法的,當(dāng)我們調(diào)用了digester.addRuleSet(new EngineRuleSet("Server/Service/"));方法,Digester便會(huì)自動(dòng)調(diào)用到EngineRuleSet類的addRuleInstances方法,在方法里面無(wú)非也是添加各種模式和規(guī)則,根據(jù)上面的添加規(guī)則,很容易知道這里又添加了一個(gè)StandardEngine對(duì)象(容器),然后又在該模式的上一級(jí)模式Server/Service添加StandardEngine跟StandardService的關(guān)系,即通過(guò)setContainer方法把容器添加進(jìn)StandardService里。以下是StandardService的setContainer方法:

  1. public ? void ?setContainer(Container?container)?{??
  2. ?????Container?oldContainer?=? this .container;??
  3. ????? if ?((oldContainer?!=? null )?&&?(oldContainer? instanceof ?Engine))??
  4. ?????????((Engine)?oldContainer).setService( null );??
  5. ????? this .container?=?container;??
  6. ????? if ?(( this .container?!=? null )?&&?( this .container? instanceof ?Engine))??
  7. ?????????((Engine)? this .container).setService( this );??
  8. ????? if ?(started?&&?( this .container?!=? null )?&&??
  9. ?????????( this .container? instanceof ?Lifecycle))?{??
  10. ????????? try ?{??
  11. ?????????????((Lifecycle)? this .container).start();??
  12. ?????????}? catch ?(LifecycleException?e)?{??
  13. ?????????????;??
  14. ?????????}??
  15. ?????}????????????????????????????????????? //重點(diǎn)?。。。。。。?! ??
  16. ????? synchronized ?(connectors)?{??????????? //下面是把StandardService下的所有連接器都關(guān)聯(lián)上StandardService下的容器,這樣連接器就跟容器關(guān)聯(lián)上了。 ??
  17. ????????? for ?( int ?i?=? 0 ;?i?<?connectors.length;?i++)??
  18. ?????????????connectors[i].setContainer( this .container);??
  19. ?????}??
  20. ????? if ?(started?&&?(oldContainer?!=? null )?&&??
  21. ?????????(oldContainer? instanceof ?Lifecycle))?{??
  22. ????????? try ?{??
  23. ?????????????((Lifecycle)?oldContainer).stop();??
  24. ?????????}? catch ?(LifecycleException?e)?{??
  25. ?????????????;??
  26. ?????????}??
  27. ?????}??
  28. ??
  29. ????? //?Report?this?property?change?to?interested?listeners ??
  30. ?????support.firePropertyChange( "container" ,?oldContainer,? this .container);??
  31. ??
  32. ?}??

上面的代碼做了各種判斷,然后把容器設(shè)置到StandardService下,在“同步代碼塊”處,把容器和鏈接器關(guān)聯(lián)上了,至此,容器和鏈接器就關(guān)聯(lián)上了?;剡^(guò)頭想想,其實(shí)很簡(jiǎn)單,就是用Digester根據(jù)設(shè)定的模式讀取server.xml,然后調(diào)用了兩個(gè)關(guān)鍵的方法setContainer和addConnector,就把容器和鏈接器關(guān)聯(lián)上了。關(guān)聯(lián)上了就可以明白在 Tomcat源碼分析(二)--連接處理 一文的最后process方法里代碼: connector.getContainer().invoke(request,?response);的含義了。下篇希望說(shuō)明白調(diào)用invoke之后發(fā)生的一切。

Tomcat源碼分析(三)--連接器是如何與容器關(guān)聯(lián)的?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!??!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論