Web.xml詳解

Web.xml加載過程(步驟)

首先簡單說一下,web.xml的加載過程。 當咱們去啓動一個WEB項目時,容器包括(JBoss、Tomcat等)首先會讀取項目web.xml配置文件裏的配置,當這一步驟沒有出錯而且完成以後,項目才能正常地被啓動起來。html

  • 啓動WEB項目的時候,容器首先會去它的配置文件web.xml讀取兩個節點:
<listener></listener>

java

<context-param></context-param>
  • 緊接着,容器建立一個 ServletContext(application),這個WEB項目全部部分都將共享這個上下文。
  • 容器以 <context-param></context-param>name 做爲鍵,value做爲值,將其轉化爲鍵值對,存入ServletContext
  • 容器建立 <listener></listener> 中的類實例,根據配置的 class 類路徑 <listener-class> 來建立監聽,在監聽中會有 contextInitialized(ServletContextEvent args) 初始化方法,啓動 Web 應用時,系統調用 Listener 的該方法,在這個方法中得到:
ServletContext application =ServletContextEvent.getServletContext();
context-param的值= application.getInitParameter("context-param的鍵");

獲得這個context-param的值以後,你就能夠作一些操做了web

  • 舉例:你可能想在項目啓動以前就打開數據庫,那麼這裏就能夠在<context-param>中設置 數據庫的鏈接方式(驅動、url、user、password),在監聽類中初始化數據庫的鏈接。 這個監聽是本身寫的一個類,除了初始化方法,它還有銷燬方法,用於關閉應用前釋放資源。 好比:說數據庫鏈接的關閉,此時,調用contextDestroyed(ServletContextEvent args),關閉Web應用時,系統調用Listener的該方法。
  • 接着,容器會讀取**<filter></filter>**,根據指定的類路徑來實例化過濾器。
  • 以上都是在WEB項目尚未徹底啓動起來的時候就已經完成了的工做。若是系統中有Servlet,則Servlet是在第一次發起請求的時候被實例化的,並且通常不會被容器銷燬,它能夠服務於多個用戶的請求。因此,Servlet的初始化都要比上面提到的那幾個要遲。

總的來講,web.xml 的加載順序是: <context-param> -> <listener> -> <filter> -> <servlet> 。其中,若是 web.xml 中出現了相同的元素,則按照在配置文件中出現的前後順序來加載。spring

對於某類元素而言,與它們出現的順序是有關的。以 <filter> 爲例,web.xml中固然能夠定義多個 <filter>,與 <filter> 相關的一個元素是 <filter-mapping>,注意,對於擁有相同 <filter-name><filter><filter-mapping> 元素而言,<filter-mapping> 必須出如今 <filter> 以後,不然當解析到 <filter-mapping> 時,它所對應的 <filter-name> 還未定義。web容器啓動初始化每一個 <filter>時,按照 <filter> 出現的順序來初始化的,當請求資源匹配多個 <filter-mapping> 時,<filter> 攔截資源是按照 <filter-mapping> 元素出現的順序來依次調用 doFilter() 方法的。<servlet><filter> 相似,此處再也不贅述。數據庫

web.xml標籤詳解

1. **XML**文檔有效性檢查

部署描述符的根元素是**<web-app>。DTD文件規定<web-app>**元素的子元素的語法以下:tomcat

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

這段代碼指定文件類型定義(DTD),能夠經過它檢查XML文檔的有效性。下面顯示的<!DOCTYPE>元素有幾個特性,這些特性告訴咱們關於DTD的信息:session

  • **web-app定義該文檔(部署描述符,不是DTD**文件)的根元素
  • **PUBLIC意味着DTD**文件能夠被公開使用
  • _ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"_意味着DTDSun Microsystems, Inc.維護。該信息也表示它描述的文檔類型是**DTD Web Application 2.3,並且DTD**是用英文書寫的。
  • URL"http://java.sun.com/dtd/web-app_2_3.dtd" 表示D文件的位置。

2. <web-app></web-app>

<!ELEMENT web-app (icon?, display-name?, description?, 
distributable?, context-param*, filter*, filter-mapping*, 
listener*, servlet*, servlet-mapping*, session-config?, 
mime-mapping*, welcome-file-list?, 
error-page*, taglib*, resource-env-ref*, resource-ref*, 
security-constraint*, login-config?, security-role*,env-entry*, 
ejb-ref*, ejb-local-ref*)>

正如您所看到的,這個元素含有23個子元素,並且子元素都是可選的。問號**(?)**表示子元素是可選的,並且只能出現一次。星號 (*) 表示子元素可在部署描述符中出現零次或屢次。有些子元素還能夠有它們本身的子元素。 web.xml 文件中 **<web-app>**元素聲明的是下面每一個子元素的聲明。下面講述部署描述符中可能包含的全部子元素。app

ps:在Servlet 2.3中,子元素必須按照DTD文件語法描述中指定的順序出現。好比:若是部署描述符中的<web-app>元素有<servlet>和<servlet-mapping>兩個子元素,則<servlet>子元素必須出如今<servlet-mapping>子元素以前。在Servlet2.4中,順序並不重要。dom

3.<display-name></display-name>

<display-name>test-hwp-web-application</display-name>定義了web應用的名稱,能夠在http://localhost:8080/manager/html 中顯示。以下所示:webapp

輸入圖片說明

4.<distributable/>

<distributable/>可使用distributable元素來告訴servlet/JSP容器,Web容器中部署的應用程序適合在分環境下運行。

5.<context-param></context-param>

<!--****************************上下文初始化參數配***************************-->  
<context-param>  
    <param-name>webAppRootKey</param-name>  
    <param-value>business.root</param-value>  
</context-param>  
<!-- spring config -->  
<context-param>  
    <param-name>contextConfigLocation</param-name>  
    <param-value>/WEB-INF/spring-configuration/*.xml</param-value>  
</context-param>

<context-param>解釋: <context-param>元素含有一對參數名和參數值,用做應用的Servlet上下文初始化參數,參數名在整個Web應用中必須是唯一的,在web應用的整個生命週期中上下文初始化參數都存在,任意的Servlet_ jsp_ 均可以隨時隨地訪問它。<param-name> 子元素包含有參數名,而**<param-value>子元素包含的是參數值。做爲選擇,可用<description>**子元素來描述參數。

什麼狀況下使用,爲何使用<context-param>?

好比:定義一個管理員email地址用來從程序發送錯誤,或者與你整個應用程序有關的其餘設置。使用本身定義的設置文件須要額外的代碼和管理;直接在你的程序中使用硬編碼(Hard-coding)參數值會給你以後修改程序帶來麻煩,更困難的是,要根據不一樣的部署使用不一樣的設置;經過這種辦法,可讓其餘開發人員更容易找到相關的參數,由於它是一個用於設置這種參數的標準位置。

Spring配置文件:

配置**Spring,必須須要<listener>,而<context-param>無關緊要,若是在web.xml中不寫<context-param>配置信息,默認的路徑是/WEB-INF/applicationContext.xml,在WEB-INF目錄下建立的xml文件的名稱必須是applicationContext.xml。若是是要自定義文件名能夠在web.xml里加入contextConfigLocation這個context參數:在<param-value>裏指定相應的xml文件名,若是有多個xml文件,能夠寫在一塊兒並以「,」號分隔,好比在business-client工程中,咱們採用了自定義配置方式,<context-param>**配置以下:

<!-- spring config -->  
<context-param>  
    <param-name>contextConfigLocation</param-name>  
    <param-value>/WEB-INF/spring-configuration/*.xml</param-value>  
</context-param>  
<listener>  
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
 </listener>

部署在同一容器中的多個Web項目,要配置不一樣的webAppRootKey,web.xml文件中最好定義webAppRootKey參數,若是不定義,將會缺省爲「webapp.root」,以下:

<!-- 應用路徑  -->    
 <context-param>    
        <param-name>webAppRootKey</param-name>    
        <param-value>webapp.root</param-value>    
 </context-param>

固然也不能重複,不然報相似下面的錯誤:

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!

意思是「webapp.root」這個key已經指向了項目1,不能夠再指向項目2。多個項目要對webAppRootKey進行配置,咱們工程主要是讓log4j能將日誌寫到對應項目根目錄下,好比:咱們的項目的webAppRootKey爲

!—business-client應用路徑  -->    
    <context-param>    
        <param-name>webAppRootKey</param-name>    
        <param-value> business.root </param-value>    
    </context-param>    
<!—public-base應用路徑  -->    
    <context-param>    
        <param-name>webAppRootKey</param-name>    
        <param-value> pubbase.root</param-value>    
    </context-param>

這樣就不會出現衝突了。就能夠在運行時動態地找到項目路徑,在log4j.properties配置文件中能夠按下面的方式使用**${webapp.root}**:

log4j.appender.file.File=${webapp.root}/WEB-INF/logs/sample.log

就能夠在運行時動態地找出項目的路徑。

多個配置文件交叉引用處理:

若是web.xml中有contextConfigLocation參數指定的Spring配置文件,則會去加載相應的配置文件,而不會去加載/WEB-INF/下的applicationContext.xml。可是若是沒有指定的話,默認會去/WEB-INF/下加載applicationContext.xml。 在一個團隊使用Spring的實際項目中,應該須要多個Spring的配置文件,如何使用和交叉引用的問題: 多個配置文件能夠在web.xml裏用空格分隔寫入,如:

<context-param>  
<param-name>contextConfigLocation </param-name>  
<param-value> applicationContext-database.xml,applicationContext.xml</param-value>    
<context-param>

多個配置文件裏的交叉引用能夠用ref的external或bean解決,例如

applicationContext.xml

<bean id="userService" class="domain.user.service.impl.UserServiceImpl">   
<property name="dbbean">  
<ref bean="dbBean"/>  
</property>   
</bean>

dbBean在applicationContext-database.xml中。 在不一樣環境下如何獲取:

<context-param>  
<param-name>param_name</param-name>  
<param-value>param_value</param-value>  
</context-param>

此所設定的參數,在JSP網頁中可使用下列方法來取得:

${initParam.param_name}

若在Servlet可使用下列方法來得到:

String param_name=getServletContext().getInitParamter("param_name");

**ServletServletConfig對象擁有該Servlet**的 ServletContext的一個引用,因此可這樣取得上下文初始化參數:getServletConfig().getServletContext().getInitParameter()也能夠在Servlet中直接調用getServletContext().getInitParameter(),二者是等價的。

6.<session-config></session-config>

<!-- Set timeout to 120 minutes -->  
<session-config>   
<session-timeout>120</session-timeout>   
</session-config>

<session-config> 用於設置容器的**session參數,好比:<session-timeout>用於指定http session的失效時間。默認時間設置在<jakarta>/conf/web.xml (30 minutes)<session-timeout>**用來指定默認的會話超時時間間隔,以分鐘爲單位。該元素值必須爲整數。若是 session-timeout元素的值爲零或負數,則表示會話將永遠不會超時。

7. <listener></listener>

<!--****************************監聽器配置*********************************-->  
<!-- Spring的log4j監聽器 -->  
<listener>  
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  
</listener>  
<listener>  
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
</listener>  
<!-- 與CAS Single Sign Out Filter配合,註銷登陸信息  -->   
<listener>  
<listener-class>com.yonyou.mcloud.cas.client.session.SingleSignOutHttpSessionListener</listener-class>  
</listener>
  1. Listener介紹:

<listener>爲web應用程序定義監聽器,監聽器用來監聽各類事件,好比:application和session事件,全部的監聽器按照相同的方式定義,功能取決去它們各自實現的接口,經常使用的Web事件接口有以下幾個:

  • _ ServletContextListener_:用於監聽**Web**應用的啓動和關閉;
  • _ ServletContextAttributeListener_:用於監聽**ServletContext範圍(application**)內屬性的改變;
  • ServletRequestListener:用於監聽用戶的請求;
  • ServletRequestAttributeListener:用於監聽**ServletRequest範圍(request**)內屬性的改變;
  • _ HttpSessionListener_:用於監聽用戶**session**的開始和結束;
  • HttpSessionAttributeListener:用於監聽**HttpSession範圍(session**)內屬性的改變。

<listener>主要用於監聽Web應用事件,其中有兩個比較重要的WEB應用事件:應用的啓動和中止(starting up or shutting down)和**Session的建立和失效(created or destroyed)。應用啓動事件發生在應用第一次被Servlet容器裝載和啓動的時候;中止事件發生在Web應用中止的時候。Session建立事件發生在每次一個新的session建立的時候,相似地Session失效事件發生在每次一個Session失效的時候。爲了使用這些Web應用事件作些有用的事情,咱們必須建立和使用一些特殊的「監聽類」。它們是實現瞭如下兩個接口中任何一個接口的簡單java類:javax.servlet.ServletContextListenerjavax.servlet.http.HttpSessionListener,若是想讓你的類監聽應用的啓動和中止事件,你就得實現ServletContextListener接口;想讓你的類去監聽Session的建立和失效事件,那你就得實現HttpSessionListener**接口。

1.Listener配置:

  • 使用**@WebListener修飾Listener**實現類便可。
  • 在**web.xml文檔中使用<listener>**進行配置。

咱們選擇web.xml這種配置方式,只有一個元素<listener-class>指定Listener的實現類,以下所示:

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

8. <filter></filter>

<!--****************************過濾器配置*********************************-->  
  <!-- 字符集過濾器 -->  
  <filter>  
    <filter-name>CharacterEncodingFilter</filter-name>  
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
    <init-param>  
      <param-name>encoding</param-name>  
      <param-value>UTF-8</param-value>  
    </init-param>  
    <init-param>  
      <param-name>forceEncoding</param-name>  
      <param-value>true</param-value>  
    </init-param>  
  </filter>  
  <!-- 單點登出過濾器 -->  
  <filter>  
    <filter-name>CAS Single Sign Out Filter</filter-name>  
    <filter-class>com.yonyou.mcloud.cas.client.session.SingleSignOutFilter</filter-class>  
  </filter>  
  <!-- 認證過濾器 -->  
  <filter>  
    <filter-name>CAS Authentication Filter</filter-name>  
<filter-class>com.yonyou.mcloud.cas.client.authentication.ExpandAuthenticationFilter</filter-class>  
    <init-param>  
      <param-name>casServerLoginUrl</param-name>  
      <param-value>https://dev.yonyou.com:443/sso-server/login</param-value>  
    </init-param>  
    <init-param>  
      <!--這裏的server是服務端的IP -->  
      <param-name>serverName</param-name>  
      <param-value>http://10.1.215.40:80</param-value>  
    </init-param>  
  </filter>  
  <!-- 驗證ST/PT過濾器 -->  
  <filter>  
    <filter-name>CAS Validation Filter</filter-name>  
<filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>  
    <init-param>  
      <param-name>casServerUrlPrefix</param-name>  
      <param-value>https://dev.yonyou.com:443/sso-server</param-value>  
    </init-param>  
    <init-param>  
      <param-name>serverName</param-name>  
      <param-value>http://10.1.215.40:80</param-value>  
    </init-param>  
    <init-param>  
      <param-name>proxyCallbackUrl</param-name>  
      <param-value>https://dev.yonyou.com:443/business/proxyCallback</param-value>  
    </init-param>  
    <init-param>  
      <param-name>proxyReceptorUrl</param-name>  
      <param-value>/proxyCallback</param-value>  
    </init-param>  
    <init-param>  
      <param-name>proxyGrantingTicketStorageClass</param-name>  
<param-value>com.yonyou.mcloud.cas.client.proxy.MemcachedBackedProxyGrantingTicketStorageImpl</param-value>  
    </init-param>  
    <!-- 解決中文問題 -->  
    <init-param>  
      <param-name>encoding</param-name>  
      <param-value>UTF-8</param-value>  
    </init-param>  
  </filter>  
  <filter>  
    <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
    <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>  
  </filter>  
  <filter>  
    <filter-name>CAS Assertion Thread Local Filter</filter-name>  
    <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>  
  </filter>  
  <filter>  
    <filter-name>NoCache Filter</filter-name>  
    <filter-class>com.yonyou.mcloud.cas.client.authentication.NoCacheFilter</filter-class>  
  </filter>  
  <!--****************************映射關係配置********************************-->  
  <filter-mapping>  
    <filter-name>CharacterEncodingFilter</filter-name>  
    <url-pattern>/*</url-pattern>  
  </filter-mapping>  
  <filter-mapping>  
    <filter-name>NoCache Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
  </filter-mapping>  
  <filter-mapping>  
    <filter-name>CAS Single Sign Out Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
  </filter-mapping>  
  <filter-mapping>  
    <filter-name>CAS Validation Filter</filter-name>  
    <url-pattern>/proxyCallback</url-pattern>  
  </filter-mapping>  
  <filter-mapping>  
    <filter-name>CAS Authentication Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
  </filter-mapping>  
  <filter-mapping>  
    <filter-name>CAS Validation Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
  </filter-mapping>  
  <filter-mapping>  
    <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
  </filter-mapping>  
  <filter-mapping>  
    <filter-name>CAS Assertion Thread Local Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
  </filter-mapping>
相關文章
相關標籤/搜索