本文轉(zhuǎn)載自:關(guān)于web.xml配置的那些事兒 - 個(gè)人文章 - SegmentFault 思否
1.簡(jiǎn)介
web.xml文件是Java web項(xiàng)目中的一個(gè)配置文件优床,主要用于配置歡迎頁(yè)奸忽、Filter量蕊、Listener痰洒、Servlet等哨查,但并不是必須的回俐,一個(gè)java web項(xiàng)目沒有web.xml文件照樣能跑起來祭衩。Tomcat容器/conf目錄下也有作用于全局web應(yīng)用web.xml文件嚼摩,當(dāng)一個(gè)web項(xiàng)目要啟動(dòng)時(shí)钦讳,Tomcat會(huì)首先加載項(xiàng)目中的web.xml文件矿瘦,然后通過其中的配置來啟動(dòng)項(xiàng)目,只有配置的各項(xiàng)沒有錯(cuò)誤時(shí)愿卒,項(xiàng)目才能正常啟動(dòng)缚去。
那么web.xml文件中到底有些什么內(nèi)容呢?我們要如何去配置它以適應(yīng)我們的項(xiàng)目呢琼开?
首先讓我們從Tomcat加載資源的順序開始易结,一步步分析web.xml文件的作用。
2.Tomcat加載資源順序
Tomcat啟動(dòng)時(shí)加載資源主要有三個(gè)階段:
第一階段:JVM相關(guān)資源
(1)$JAVA_HOME/jre/lib/ext/*.jar(2)系統(tǒng)classpath環(huán)境變量中的*.jar和*.class
第二階段:Tomcat自身相關(guān)資源
(1)$CATALINA_HOME/common/classes/*.class(2)$CATALINA_HOME/commons/endorsed/*.jar? (3)$CATALINA_HOME/commons/i18n/*.jar? (4)$CATALINA_HOME/common/lib/*.jar(5)$CATALINA_HOME/server/classes/*.class(6)$CATALINA_HOME/server/lib/*.jar(7)$CATALINA_BASE/shared/classes/*.class(8)$CATALINA_BASE/shared/lib/*.jar
第三階段:Web應(yīng)用相關(guān)資源
(1)具體應(yīng)用的webapp目錄:/WEB-INF/classes/*.class?
(2)具體應(yīng)用的webapp: /WEB-INF/lib/*.jar
在同一個(gè)文件夾下柜候,jar包是按順序從上到下依次加載,由ClassLoader的雙親委托模式加載機(jī)制我們可以知道搞动,假設(shè)兩個(gè)包名和類名完全相同的class文件不再同一個(gè)jar包,如果一個(gè)class文件已經(jīng)被加載java虛擬機(jī)里了渣刷,那么后面的相同的class文件就不會(huì)被加載了鹦肿。
但tomcat的加載運(yùn)行機(jī)制與JAVA虛擬機(jī)的父類委托機(jī)制稍有不同。?
下面來做詳細(xì)敘述:?
1辅柴、首先加載TOMCAT_HOME/lib目錄下的jar包?
2箩溃、然后加載TOMCAT_HOME/webapps/項(xiàng)目名/WEB-INF/lib的jar包?
3、最后加載的是TOMCAT_HOME/webapps/項(xiàng)目名/WEB-INF/classes下的類文件?
值得注意的關(guān)鍵是:tomcat按上述順序依次加載資源碌嘀,當(dāng)后加載的資源與之前加載的資源相重時(shí)涣旨,后加載的資源會(huì)繼續(xù)加載并將之前的資源覆蓋。
Tomcat的具體內(nèi)部細(xì)節(jié)及解讀可以參考:
Apache Tomcat 9 (9.0.0.M26) - Documentation
極客學(xué)院wiki - 《Tomcat 8 權(quán)威指南》
3.web.xml配置文件簡(jiǎn)介
servlet和JSP規(guī)范在發(fā)展階段中出現(xiàn)了很多的web.xml配置版本股冗,如3.0霹陡、3.1、4.0等止状,版本的變更會(huì)改變web.xml對(duì)應(yīng)的配置代碼烹棉。下圖是來自Tomcat官網(wǎng)的Servlet和JSP規(guī)范規(guī)范與的Apache Tomcat版本之間的對(duì)應(yīng)關(guān)系:
下面是各個(gè)版本的web.xml配置示例代碼:
servlet 2.5 [Tomcat 6.0.x(archived)]
servlet 3.0 [Tomcat 7.0.x]
servlet 3.1 [Tomcat 8.0.x (superseded) & 8.5.x]
servlet 4.0 [Tomcat 9.0.x]
在tomcat目錄${CATALINA_HOME}/conf下和web應(yīng)用目錄${CATALINA_HOME}/webapps/WebDemo(WebDemo為web應(yīng)用名)下都有web.xml這個(gè)文件,但是內(nèi)容不一樣导俘。
Tomcat在激活峦耘、加載、部署web應(yīng)用時(shí)旅薄,會(huì)解析加載${CATALINA_HOME}/conf目錄下所有web應(yīng)用通用的web.xml,然后解析加載web應(yīng)用目錄中的WEB-INF/web.xml泣崩。
其實(shí)根據(jù)他們的位置少梁,我們就可以知道,conf/web.xml文件中的設(shè)定會(huì)應(yīng)用于所有的web應(yīng)用程序矫付,而某些web應(yīng)用程序的WEB-INF/web.xml中的設(shè)定只應(yīng)用于該應(yīng)用程序本身凯沪。
如果沒有WEB-INF/web.xml文件,tomcat會(huì)輸出找不到的消息买优,但仍然會(huì)部署并使用web應(yīng)用程序妨马,servlet規(guī)范的作者想要實(shí)現(xiàn)一種能迅速并簡(jiǎn)易設(shè)定新范圍的方法挺举,以用作測(cè)試,因此烘跺,這個(gè)web.xml并不是必要的湘纵,不過通常最好還是讓每一個(gè)上線的web應(yīng)用程序都有一個(gè)自己的WEB-INF/web.xml。
3.web.xml元素配置詳解
web.xml文件加載順序?yàn)椋?與順序無關(guān))
ServletContext -> context-param -> listener -> filter -> servlet
web.xml中定義了以下元素:
定義了WEB應(yīng)用的名字聲明WEB應(yīng)用的描述信息context-param元素聲明應(yīng)用范圍內(nèi)的初始化參數(shù)滤淳。過濾器元素將一個(gè)名字與一個(gè)實(shí)現(xiàn)javax.servlet.Filter接口的類相關(guān)聯(lián)梧喷。一旦命名了一個(gè)過濾器,就要利用filter-mapping元素把它與一個(gè)或多個(gè)servlet或JSP頁(yè)面相關(guān)聯(lián)脖咐。servlet API的版本2.3增加了對(duì)事件監(jiān)聽程序的支持铺敌,事件監(jiān)聽程序在建立、修改和刪除會(huì)話或servlet環(huán)境時(shí)得到通知屁擅。Listener元素指出事件監(jiān)聽程序類偿凭。在向servlet或JSP頁(yè)面制定初始化參數(shù)或定制URL時(shí),必須首先命名servlet或JSP頁(yè)面派歌。Servlet元素就是用來完成此項(xiàng)任務(wù)的笔喉。服務(wù)器一般為servlet提供一個(gè)缺省的URL:http://host/webAppPrefix/servlet/ServletName.? ? ? ? 但是,常常會(huì)更改這個(gè)URL硝皂,以便servlet可以訪問初始化參數(shù)或更容易地處理相對(duì)URL常挚。在更改缺省URL時(shí),使用servlet-mapping元素稽物。如果某個(gè)會(huì)話在一定時(shí)間內(nèi)未被訪問奄毡,服務(wù)器可以拋棄它以節(jié)省內(nèi)存。 可通過使用HttpSession的setMaxInactiveInterval方法明確設(shè)置單個(gè)會(huì)話對(duì)象的超時(shí)值贝或,或者可利用session-config元素制定缺省超時(shí)值吼过。如果Web應(yīng)用具有想到特殊的文件,希望能保證給他們分配特定的MIME類型咪奖,則mime-mapping元素提供這種保證盗忱。指示服務(wù)器在收到引用一個(gè)目錄名而不是文件名的URL時(shí),使用哪個(gè)文件羊赵。在返回特定HTTP狀態(tài)代碼時(shí)趟佃,或者特定類型的異常被拋出時(shí),能夠制定將要顯示的頁(yè)面昧捷。對(duì)標(biāo)記庫(kù)描述符文件(Tag Libraryu Descriptor file)指定別名闲昭。此功能使你能夠更改TLD文件的位置,而不用編輯使用這些文件的JSP頁(yè)面靡挥。聲明與資源相關(guān)的一個(gè)管理對(duì)象序矩。聲明一個(gè)資源工廠使用的外部資源。制定應(yīng)該保護(hù)的URL跋破。它與login-config元素聯(lián)合使用指定服務(wù)器應(yīng)該怎樣給試圖訪問受保護(hù)頁(yè)面的用戶授權(quán)簸淀。它與sercurity-constraint元素聯(lián)合使用瓶蝴。給出安全角色的一個(gè)列表,這些角色將出現(xiàn)在servlet元素內(nèi)的security-role-ref元素的role-name子元素中租幕。分別地聲明角色可使高級(jí)IDE處理安全信息更為容易舷手。聲明Web應(yīng)用的環(huán)境項(xiàng)。聲明一個(gè)EJB的主目錄的引用令蛉。聲明一個(gè)EJB的本地主目錄的應(yīng)用聚霜。
相應(yīng)元素的配置:
Web應(yīng)用圖標(biāo):指出IDE和GUI工具用來表示W(wǎng)eb應(yīng)用的大圖標(biāo)和小圖標(biāo)
/images/app_small.gif/images/app_large.gif
Web 應(yīng)用名稱:提供GUI工具可能會(huì)用來標(biāo)記這個(gè)特定的Web應(yīng)用的一個(gè)名稱
Tomcat Example
Web 應(yīng)用描述: 給出于此相關(guān)的說明性文本
Tomcat Example servlets and JSP pages.
上下文參數(shù):聲明應(yīng)用范圍內(nèi)的初始化參數(shù)。
ContextParametertestIt is a test parameter.
在servlet里面可以通過getServletContext().getInitParameter("context/param")得到珠叔。
過濾器配置:將一個(gè)名字與一個(gè)實(shí)現(xiàn)javaxs.servlet.Filter接口的類相關(guān)聯(lián)蝎宇。
setCharacterEncodingcom.myTest.setCharacterEncodingFilterencodingGB2312setCharacterEncoding/*
監(jiān)聽器配置
listener.SessionListener
Servlet配置?
基本配置
snoopSnoopServletsnoop/snoop
高級(jí)配置
snoopSnoopServletfoobarSecurity role for anonymous accesstomcatsnoop/snoop
元素說明
用來聲明一個(gè)servlet的數(shù)據(jù),主要有以下子元素:指定servlet的名稱指定servlet的類名稱指定web站臺(tái)中的某個(gè)JSP網(wǎng)頁(yè)的完整路徑用來定義參數(shù)祷安,可有多個(gè)init-param姥芥。在servlet類中通過getInitParamenter(String name)方法訪問初始化參數(shù)指定當(dāng)Web應(yīng)用啟動(dòng)時(shí),裝載Servlet的次序汇鞭。 當(dāng)值為正數(shù)或零時(shí):Servlet容器先加載數(shù)值小的servlet凉唐,再依次加載其他數(shù)值大的servlet. 當(dāng)值為負(fù)或未定義:Servlet容器將在Web客戶首次訪問這個(gè)servlet時(shí)加載它用來定義servlet所對(duì)應(yīng)的URL,包含兩個(gè)子元素指定servlet的名稱指定servlet所對(duì)應(yīng)的URL
會(huì)話超時(shí)配置(單位為分鐘)
120
MIME類型配置
htmtext/html
指定歡迎文件頁(yè)配置
index.jspindex.htmlindex.htm
配置錯(cuò)誤頁(yè)面
方法1:通過錯(cuò)誤碼來配置error-page
404/NotFound.jsp
上面配置了當(dāng)系統(tǒng)發(fā)生404錯(cuò)誤時(shí)霍骄,跳轉(zhuǎn)到錯(cuò)誤處理頁(yè)面NotFound.jsp台囱。 方法2:通過異常的類型配置error-page
java.lang.NullException/error.jsp
上面配置了當(dāng)系統(tǒng)發(fā)生java.lang.NullException(即空指針異常)時(shí),跳轉(zhuǎn)到錯(cuò)誤處理頁(yè)面error.jsp
TLD配置
http://jakarta.apache.org/tomcat/debug-taglib/WEB-INF/jsp/debug-taglib.tld
如果MyEclipse一直在報(bào)錯(cuò),應(yīng)該把放到中
http://jakarta.apache.org/tomcat/debug-taglib/WEB-INF/pager-taglib.tld
資源管理對(duì)象配置
jms/StockQueue
資源工廠配置
mail/Sessionjavax.mail.SessionContainer
配置數(shù)據(jù)庫(kù)連接池就可在此配置:
JNDI JDBC DataSource of shopjdbc/sample_dbjavax.sql.DataSourceContainer
安全限制配置
Example Security ConstraintProtected Area/jsp/security/protected/*DELETEGETPOSTPUTtomcatrole1
登陸驗(yàn)證配置
FORMExample-Based Authentiation Area/jsp/security/protected/login.jsp/jsp/security/protected/error.jsp
安全角色:security-role元素給出安全角色的一個(gè)列表读整,這些角色將出現(xiàn)在servlet元素內(nèi)的security-role-ref元素的role-name子元素中簿训。?
分別地聲明角色可使高級(jí)IDE處理安全信息更為容易。
tomcat
Web環(huán)境參數(shù):env-entry元素聲明Web應(yīng)用的環(huán)境項(xiàng)
minExemptions1java.lang.Integer
EJB 聲明
Example EJB referenceejb/AccountEntitycom.mycompany.mypackage.AccountHomecom.mycompany.mypackage.Account
本地EJB聲明
Example Loacal EJB referenceejb/ProcessOrderSessioncom.mycompany.mypackage.ProcessOrderHomecom.mycompany.mypackage.ProcessOrder
配置DWR
dwr-invokeruk.ltd.getahead.dwr.DWRServletdwr-invoker/dwr/*
4.spring項(xiàng)目中web.xml基礎(chǔ)配置
配置基于servlet 3.1
demodemo
? ? 下面我們來看看Spring框架給我們提供過濾器CharacterEncodingFilter?
? ? 這個(gè)過濾器就是針對(duì)于每次瀏覽器請(qǐng)求進(jìn)行過濾的米间,然后再其之上添加了父類沒有的功能即處理字符編碼强品。?
? ? ? 其中encoding用來設(shè)置編碼格式,forceEncoding用來設(shè)置是否理會(huì) request.getCharacterEncoding()方法屈糊,設(shè)置為true則強(qiáng)制覆蓋之前的編碼格式的榛。-->characterEncodingFilterorg.springframework.web.filter.CharacterEncodingFilterencodingUTF-8forceEncodingtruecharacterEncodingFilter/*
? ? 在ContextLoaderListener中關(guān)聯(lián)了ContextLoader這個(gè)類,所以整個(gè)加載配置過程由ContextLoader來完成逻锐。?
? ? 它的API說明?
? ? 第一段說明ContextLoader可以由 ContextLoaderListener和ContextLoaderServlet生成夫晌。?
? ? 如果查看ContextLoaderServlet的API,可以看到它也關(guān)聯(lián)了ContextLoader這個(gè)類而且它實(shí)現(xiàn)了HttpServlet? ? 這個(gè)接口?
? ? 第二段谦去,ContextLoader創(chuàng)建的是 XmlWebApplicationContext這樣一個(gè)類慷丽,它實(shí)現(xiàn)的接口是WebApplicationContext->ConfigurableWebApplicationContext->ApplicationContext->?
? ? BeanFactory這樣一來spring中的所有bean都由這個(gè)類來創(chuàng)建?
? ? IUploaddatafileManager uploadmanager = (IUploaddatafileManager)?
? ? ContextLoaderListener.getCurrentWebApplicationContext().getBean("uploadManager");-->org.springframework.web.context.ContextLoaderListener
? ? 在WEB-INF目錄下創(chuàng)建的xml文件的名稱必須是applicationContext.xml。?
? ? 如果是要自定義文件名可以在web.xml里加入contextConfigLocation這個(gè)context參數(shù):?
? ? 在 里指定相應(yīng)的xml文件名鳄哭,如果有多個(gè)xml文件,可以寫在一起并以“,”號(hào)分隔纲熏。?
? ? 也可以這樣applicationContext-*.xml采用通配符妆丘,比如這那個(gè)目錄下有applicationContext-ibatis-base.xml锄俄,?
? ? applicationContext-action.xml,applicationContext-ibatis-dao.xml等文件勺拣,都會(huì)一同被載入奶赠。?
? ? 在ContextLoaderListener中關(guān)聯(lián)了ContextLoader這個(gè)類,所以整個(gè)加載配置過程由ContextLoader來完成药有。-->contextConfigLocationclasspath:spring/applicationContext.xmldefault*.cssdefault*.swfdefault*.gifdefault*.jpgdefault*.pngdefault*.jsdefault*.htmldefault*.xmldefault*.jsondefault*.mapDispatcherServletorg.springframework.web.servlet.DispatcherServletcontextConfigLocation**.xml 這里可以使用多種寫法-->-servlet.xml-->/WEB-INF/classes/dispatcher-servlet.xml-->classpath*:dispatcher-servlet.xml-->classpath:spring/dispatcher-servlet.xml1DispatcherServlet/login.html404/nopage.htmljava.lang.NullPointerException/error.html360
5.流行的web.xml零配置
servlet3.0+規(guī)范后毅戈,允許servlet,filter愤惰,listener不必聲明在web.xml中苇经,而是以硬編碼的方式存在,實(shí)現(xiàn)容器的零配置宦言。
spring框架提供了一些類如WebApplicationInitializer用來配置web.xml扇单,這意味著我們可以舍棄web.xml,僅僅在主程序代碼中進(jìn)行配置奠旺。
spring的“約定大于配置”思想也體現(xiàn)在這里蜘澜,用java注解來優(yōu)化過去繁雜的xml文件配置,大大提高了開發(fā)者的編程速度和體驗(yàn)响疚。
現(xiàn)在很流行的spring boot框架鄙信,只要幾步就可以搭建一個(gè)java web項(xiàng)目,根本無需自己手動(dòng)配置web.xml忿晕,框架已經(jīng)為你提供了足夠多的注解装诡、接口及實(shí)現(xiàn)類,讓我們能夠?qū)W⒂趹?yīng)用本身杏糙。
有關(guān)spring對(duì)web.xml配置的隱藏實(shí)現(xiàn)細(xì)節(jié)慎王,這里就不詳細(xì)展開了,歡迎關(guān)注我的下一篇博客宏侍。
6.參考資料
Apache Tomcat 9 (9.0.0.M26) - Documentation
極客學(xué)院wiki - 《Tomcat 8 權(quán)威指南》
tomcat下的web.xml和web工程下web.xml的區(qū)別