一渺鹦、web.xml加載過(guò)程
簡(jiǎn)單說(shuō)一下,web.xml的加載過(guò)程塞颁。當(dāng)我們啟動(dòng)一個(gè)WEB項(xiàng)目容器時(shí)祠锣,容器包括(JBoss,Tomcat等)伴网。首先會(huì)去讀取web.xml配置文件里的配置妆棒,當(dāng)這一步驟沒(méi)有出錯(cuò)并且完成之后糕珊,項(xiàng)目才能正常的被啟動(dòng)起來(lái)。
啟動(dòng)WEB項(xiàng)目的時(shí)候刺啦,容器首先會(huì)去讀取web.xml配置文件中的兩個(gè)節(jié)點(diǎn):<listener> </listener>和<context-param> </context-param>如圖:
緊接著玛瘸,容器創(chuàng)建一個(gè)ServletContext(application),這個(gè)web項(xiàng)目的所有部分都將共享這個(gè)上下文糊渊。容器以<context-param></context-param>的name作為鍵慧脱,value作為值,將其轉(zhuǎn)化為鍵值對(duì)宗兼,存入ServletContext殷绍。
容器創(chuàng)建<listener></listener>中的類實(shí)例,根據(jù)配置的class類路徑<listener-class>來(lái)創(chuàng)建監(jiān)聽(tīng)茶行,在監(jiān)聽(tīng)中會(huì)有初始化方法登钥,啟動(dòng)Web應(yīng)用時(shí)牧牢,系統(tǒng)調(diào)用Listener的該方法 contextInitialized(ServletContextEvent args),在這個(gè)方法中獲得:
ServletContext application =ServletContextEvent.getServletContext();
context-param的值= application.getInitParameter("context-param的鍵");
得到這個(gè)context-param的值之后度陆,你就可以做一些操作了懂傀。
舉例:你可能想在項(xiàng)目啟動(dòng)之前就打開(kāi)數(shù)據(jù)庫(kù)蜡感,那么這里就可以在<context-param>中設(shè)置數(shù)據(jù)庫(kù)的連接方式(驅(qū)動(dòng)郑兴、url、user叽粹、password)虫几,在監(jiān)聽(tīng)類中初始化數(shù)據(jù)庫(kù)的連接挽拔。這個(gè)監(jiān)聽(tīng)是自己寫的一個(gè)類螃诅,除了初始化方法状囱,它還有銷毀方法亭枷,用于關(guān)閉應(yīng)用前釋放資源。比如:說(shuō)數(shù)據(jù)庫(kù)連接的關(guān)閉匹表,此時(shí),調(diào)用contextDestroyed(ServletContextEvent args)默蚌,關(guān)閉Web應(yīng)用時(shí)绸吸,系統(tǒng)調(diào)用Listener的該方法锦茁。
接著叉存,容器會(huì)讀取<filter></filter>,根據(jù)指定的類路徑來(lái)實(shí)例化過(guò)濾器稿存。
以上都是在WEB項(xiàng)目還沒(méi)有完全啟動(dòng)起來(lái)的時(shí)候就已經(jīng)完成了的工作瓣履。如果系統(tǒng)中有Servlet练俐,則Servlet是在第一次發(fā)起請(qǐng)求的時(shí)候被實(shí)例化的腺晾,而且一般不會(huì)被容器銷毀,它可以服務(wù)于多個(gè)用戶的請(qǐng)求脯宿。所以泉粉,Servlet的初始化都要比上面提到的那幾個(gè)要遲榴芳】吒校總的來(lái)說(shuō)柿祈,web.xml的加載順序是: <context-param>-> <listener> -> <filter> -> <servlet>躏嚎。其中,如果web.xml中出現(xiàn)了相同的元素卢佣,則按照在配置文件中出現(xiàn)的先后順序來(lái)加載虚茶。
二嘹叫、web.xml標(biāo)簽詳解
1.<web-app></web-app>
<web-app></web-app>是部署描述的根元素诈乒,該元素含23個(gè)子元素抓谴。在Servlet2.3中癌压,子元素必須按照DTD文件描述中指定的順序出現(xiàn)。比如:如果部署描述符中的<web-app>元素有<servlet>和<servlet-mapping>兩個(gè)子元素集侯,則<servlet>子元素必須出現(xiàn)在<servlet-mapping>子元素之前棠枉。在Servlet2.4中辈讶,順序并不重要娄猫。
2.<display-name></display-name>
<display-name></display-name>定義web應(yīng)用的名稱。如<display-name>trk-order-rest</display-name>
3.<distributable/>
<distributable/>可以使用distributable元素來(lái)告訴servlet/JSP容器碍讯,Web容器中部署的應(yīng)用程序適合在分布式環(huán)境下運(yùn)行扯躺。
4.<context-param></context-param>
<context-param>元素含有一對(duì)參數(shù)名和參數(shù)值倍啥,用作應(yīng)用的Servlet上下文初始化參數(shù),參數(shù)名在整個(gè)Web應(yīng)用中必須是惟一的逗栽,在web應(yīng)用的整個(gè)生命周期中上下文初始化參數(shù)都存在失暂,任意的Servlet和jsp都可以隨時(shí)隨地訪問(wèn)它弟塞。<param-name>子元素包含有參數(shù)名拙已,而<param-value>子元素包含的是參數(shù)值倍踪。作為選擇建车,可用<description>子元素來(lái)描述參數(shù)。
配置Spring潮罪,必須需要<listener>嫉到,而<context-param>可有可無(wú),如果在web.xml中不寫<context-param>配置信息月洛,默認(rèn)的路徑是/WEB-INF/applicationContext.xml何恶,在WEB-INF目錄下創(chuàng)建的xml文件的名稱必須是applicationContext.xml。如果是要自定義文件名可以在web.xml里加入contextConfigLocation這個(gè)context參數(shù):在<param-value>里指定相應(yīng)的xml文件名嚼黔,如果有多個(gè)xml文件导而,可以寫在一起并以“,”號(hào)分隔忱叭,比如在business-client工程中,我們采用了自定義配置方式今艺,<context-param>配置如下:
配置在同一個(gè)容器中的多個(gè)web項(xiàng)目韵丑,要配置不同的webAppRootKey,web.xml文件中最好定義webAppRootKey參數(shù)撵彻,如果不定義,將會(huì)缺省為“webapp.root”碗短,為防止log4j配置沖突,每個(gè)項(xiàng)目配置不同的webAppRootKey巡雨。如下:
當(dāng)然也不能重復(fù),否則報(bào)類似下面的錯(cuò)誤:
Web app root system property already set to different value: 'webapp.root' = [/home/user/tomcat/webapps/project1/] instead of [/home/user/tomcat/webapps/project2/] - Choose unique values for the 'webAppRootKey' context-param in your web.xml files!
5.<session-config></session-config>
<session-config> 用于設(shè)置容器的session參數(shù)营曼,比如:<session-timeout>用于指定http session的失效時(shí)間徊件。默認(rèn)時(shí)間設(shè)置(30minutes)。<session-timeout>用來(lái)指定默認(rèn)的會(huì)話超時(shí)時(shí)間間隔部翘,以分鐘為單位窖梁。該元素值為整數(shù)。如果 session-timeout元素的值為零或負(fù)數(shù)假哎,則表示會(huì)話將永遠(yuǎn)不會(huì)超時(shí)。
6.<filter></filter>見(jiàn)我的博客,這里不在闡述香嗓。(http://www.cnblogs.com/vanl/p/5742501.html)
7.<listener></listener>見(jiàn)我的博客洁灵,這里不在闡述。(http://www.cnblogs.com/vanl/p/5753722.html)
8.<servlet></servlet>
8.1.Servlet介紹
Servlet通常稱為服務(wù)端小程序,是服務(wù)端的程序牍汹,用于處理及響應(yīng)客戶的請(qǐng)求慎菲。Servlet是一個(gè)特殊的Java類,創(chuàng)建Servlet類自動(dòng)繼承HttpServlet抑党。客戶端通常只有GET和POST兩種請(qǐng)求方式苛骨,Servlet為了響應(yīng)這兩種請(qǐng)求,必須重寫doGet()和doPost()方法严衬。大部分時(shí)候赠幕,Servlet對(duì)于所有的請(qǐng)求響應(yīng)都是完全一樣的竖慧,此時(shí)只需要重寫service()方法即可響應(yīng)客戶端的所有請(qǐng)求魏蔗。另外HttpServlet有兩個(gè)方法:
init(ServletConfig config):創(chuàng)建Servlet實(shí)例時(shí)廓鞠,調(diào)用該方法初始化Servlet資源。
destory():銷毀Servlet實(shí)例時(shí)夕土,自動(dòng)調(diào)用該方法回收資源。
通常無(wú)需重寫init()和destory()兩個(gè)方法减细,除非需要在初始化Servlet時(shí),完成某些資源初始化的方法萧吠,才考慮重寫init()方法。如果重寫了init()方法狰腌,應(yīng)該在重寫該方法的第一行調(diào)用super.init(config),該方法將調(diào)用HttpServlet的init()方法。如果需要在銷毀Servlet之前踱葛,先完先完成某些資源的回收圾笨,比如關(guān)閉數(shù)據(jù)庫(kù)鏈接胶滋,才需要重寫destory()方法后德。
8.2.Servlet的生命周期
創(chuàng)建Servlet實(shí)例有兩個(gè)時(shí)機(jī):
客戶端第一次請(qǐng)求某個(gè)Servlet時(shí),系統(tǒng)創(chuàng)建該Servlet的實(shí)例,大部分Servlet都是這種Servlet;
web應(yīng)用啟動(dòng)時(shí)立即創(chuàng)建Servlet實(shí)例旺嬉,即<load-on-start>1</laod-on-start>(LZ有篇文章詳細(xì)說(shuō)明:http://www.cnblogs.com/vanl/p/5756122.html)
每個(gè)Servlet的運(yùn)行都遵循如下生命周期:
(1)創(chuàng)建Servlet實(shí)例悲酷。
(2)Web容器調(diào)用Servlet的init()方法顿肺,對(duì)Servlet進(jìn)行初始化耕拷。
(3)Servlet初始化之后赃绊,將一直存在與容器之中,用于響應(yīng)客戶端請(qǐng)求肤视,如果客戶端發(fā)送GET請(qǐng)求困后,容器調(diào)用Servlet的doGet()方法處理并響應(yīng)請(qǐng)求侧戴;如果客戶端發(fā)送POST請(qǐng)求蜕猫,容器調(diào)用Servlet的doPost()方法處理并響應(yīng)請(qǐng)求翔烁〖彰樱或者統(tǒng)一使用service()方法處理來(lái)響應(yīng)用戶請(qǐng)求鸟赫。
(4)Web容器決定銷毀Servlet時(shí)朋沮,先調(diào)用Servlet的destory()方法筋夏,通常在關(guān)閉Web應(yīng)用時(shí)銷毀Servlet實(shí)例赴叹。
8.3.Servlet的配置
為了讓Servlet能響應(yīng)用戶請(qǐng)求摊欠,還必須將Servlet配置在web應(yīng)用中免糕,配置Servlet需要修改web.xml文件蚓炬。從Servlet3.0開(kāi)始,配置Servlet有兩種方式:
(1)在Servlet類中使用基于注解的方式進(jìn)行配置:@WebServlet
(2)在web.xml文件中進(jìn)行配置。
我們用web.xml文件來(lái)配置Servlet择吊,需要配置<servlet>和<servlet-mapping>枉长。<servlet>用來(lái)聲明一個(gè)Servlet吼蚁。<icon>旗国、<display-name>和<description>元素的用法和<filter>的用法相同。<init-param>元素與<context-param>元素具有相同的元素描述符,可以使用<init-param>子元素將初始化參數(shù)名和參數(shù)值傳遞給Servlet捌治,訪問(wèn)Servlet配置參數(shù)通過(guò)ServletConfig對(duì)象來(lái)完成,ServletConfig提供如下方法:
java.lang.String.getInitParameter(java.lang.String name):用于獲取初始化參數(shù)
ServletConfig獲取配置參數(shù)的方法和ServletContext獲取配置參數(shù)的方法完全一樣浑娜,只是ServletContex是取得當(dāng)前Servlet的配置參數(shù)编饺,而ServletContext是獲取整個(gè)web應(yīng)用的配置參數(shù)秽誊。
8.4.配置Spring MVC的Servlet
配置Spring MVC耘纱,指定處理請(qǐng)求的Servlet员寇,有兩種方式:
(1)默認(rèn)查找MVC配置文件的地址是:/WEB-INF/${servletName}-servlet.xml慌闭。
(2)可以通過(guò)修改配置文件的位置,需要在配置DispatcherServlet時(shí)指定MVC配置文件的位置。
我們?cè)谄脚_(tái)項(xiàng)目?jī)蓚€(gè)工程中分別使用了不同的配置方式蔫慧,介紹如下:
我們?cè)赽usiness-client工程中按照默認(rèn)方式查找MVC的配置文件卖怜,配置文件目錄為: /WEB-INF/business-servlet.xml。工程目錄結(jié)構(gòu)如下所示:
我們?cè)趐ublic-base-server工程中揖赴,通過(guò)第2種方式進(jìn)行配置腔稀,把spring-servlet.xml放到src/main/resources/config/spring-servlet.xml炼团,則需要在配置DispatcherServlet時(shí)指定<init-param>標(biāo)簽晤郑。具體代碼如下:
工程目錄結(jié)構(gòu)如下:
其中,classpath是web項(xiàng)目的類路徑寓落,可以理解為classes目錄下面构资。因?yàn)闊o(wú)論這些配置文件放在哪里唉窃,編譯之后沒(méi)有特殊情況的話都直接在classes下面。在我們的工程里兄猩,經(jīng)過(guò)驗(yàn)證掏导,maven工程這兩個(gè)
路徑經(jīng)過(guò)編譯后生成的文件都位于classes目錄下搀愧,即這兩個(gè)路徑相當(dāng)于類路徑,在下面創(chuàng)建config文件夾(folder),創(chuàng)建自定義的xml配置文件即可奕塑。
8.5.classpath與classpath*區(qū)別
同名資源存在時(shí)圃泡,classpath只從第一個(gè)符合條件的classpath中加載資源,而classpath會(huì)從所有的classpath中加載符合條件的資源碍沐。classpath,需要遍歷所有的classpath骑科,效率肯定比不上classpath呛凶,因此在項(xiàng)目設(shè)計(jì)的初期就盡量規(guī)劃好資源文件所在的路徑,避免使用classpath*來(lái)加載。
8.6.ContextLoaderListener和DispatcherServlet初始化上下文關(guān)系和區(qū)別
從上圖可以看出,ContextLoaderListener初始化的上下文加載的Bean是對(duì)于整個(gè)應(yīng)用程序共享的匀们,一般如:DAO層宴猾、Service層Bean油讯;DispatcherServlet初始化的上下文加載的Bean是只對(duì)Spring MVC有效的Bean兔综,如:Controller固该、HandlerMapping著淆、HandlerAdapter等,該初始化上下文只加載Web相關(guān)組件拴疤。
注意:用戶可以配置多個(gè)DispatcherServlet來(lái)分別處理不同的url請(qǐng)求永部,每個(gè)DispatcherServlet上下文都對(duì)應(yīng)一個(gè)自己的子Spring容器,他們都擁有相同的父Spring容器(業(yè)務(wù)層呐矾,持久(dao)bean所在的容器)苔埋。
9.<welcome-file-list></welcome-file-list>
<welcome-file-list>包含一個(gè)子元素<welcome-file>,<welcome-file>用來(lái)指定首頁(yè)文件名稱蜒犯。<welcome-file-list>元素可以包含一個(gè)或多個(gè)<welcome-file>子元素组橄。如果在第一個(gè)<welcome-file>元素中沒(méi)有找到指定的文件,Web容器就會(huì)嘗試顯示第二個(gè)罚随,以此類推玉工。
轉(zhuǎn)自:https://blog.csdn.net/qq_22075041/article/details/78692780