1. 程式人生 > >java web工程web.xml配置詳解

java web工程web.xml配置詳解

Web.xml詳解:

1.web.xml載入過程(步驟)

首先簡單講一下,web.xml的載入過程。當啟動一個WEB專案時,容器包括(JBoss、Tomcat等)首先會讀取專案web.xml配置檔案裡的配置,當這一步驟沒有出錯並且完成之後,專案才能正常地被啟動起來。

1. 啟動WEB專案的時候,容器首先會去它的配置檔案web.xml讀取兩個節點:  <listener></listener>和<context-param></context-param>。

2. 緊接著,容器建立一個ServletContext(application),這個WEB專案所有部分都將共享這個上下文。

3. 容器以<context-param></context-param>的name作為鍵,value作為值,將其轉化為鍵值對,存入ServletContext。

4. 容器建立<listener></listener>中的類例項,根據配置的class類路徑<listener-class>來建立監聽,在監聽中會有contextInitialized(ServletContextEvent args)初始化方法,啟動Web應用時,系統呼叫Listener的該方法,在這個方法中獲得:

<span style="font-family:Times New Roman;">ServletContextapplication=ServletContextEvent.getServletContext();</span>  

context-param的值就是application.getInitParameter("context-param的鍵");得到這個context-param的值之後,你就可以做一些操作了。

5. 舉例:你可能想在專案啟動之前就開啟資料庫,那麼這裡就可以在<context-param>中設定資料庫的連線方式(驅動、url、user、password),在監聽類中初始化資料庫的連線。這個監聽是自己寫的一個類,除了初始化方法,它還有銷燬方法,用於關閉應用前釋放資源。比如:說資料庫連線的關閉,此時,呼叫contextDestroyed(ServletContextEvent args),關閉Web應用時,系統呼叫Listener的該方法。

6. 接著,容器會讀取<filter></filter>,根據指定的類路徑來例項化過濾器。

7. 以上都是在WEB專案還沒有完全啟動起來的時候就已經完成了的工作。如果系統中有Servlet,則Servlet是在第一次發起請求的時候被例項化的,而且一般不會被容器銷燬,它可以服務於多個使用者的請求。所以,Servlet的初始化都要比上面提到的那幾個要遲。

8. 總的來說,web.xml的載入順序是:<context-param>-><listener>-><filter>-><servlet>。其中,如果web.xml中出現了相同的元素,則按照在配置檔案中出現的先後順序來載入。

9. 對於某類元素而言,與它們出現的順序是有關的。以<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>類似,此處不再贅述。

2.web.xml標籤詳解

1. XML文件有效性檢查

<span style="font-family:Times New Roman;"><!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ></span>

這段程式碼指定檔案型別定義(DTD),可以通過它檢查XML文件的有效性。下面顯示的<!DOCTYPE>元素有幾個特性,這些特性告訴我們關於DTD的資訊: 

  1.  web-app定義該文件(部署描述符,不是DTD檔案)的根元素 
  2.  PUBLIC意味著DTD檔案可以被公開使用 
  3.  -//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”意味著DTD由Sun Microsystems, Inc.維護。該資訊也表示它描述的文件型別是DTD Web Application 2.3,而且DTD是用英文書寫的。 

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

部署描述符的根元素是<web-app>。DTD檔案規定<web-app>元素的子元素的語法如下:

<span style="font-family:Times New Roman;"><!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*)> </span>

正如您所看到的,這個元素含有23個子元素,而且子元素都是可選的。問號(?)表示子元素是可選的,而且只能出現一次。星號(*)表示子元素可在部署描述符中出現零次或多次。有些子元素還可以有它們自己的子元素。web.xml檔案中<web-app>元素宣告的是下面每個子元素的宣告。下面講述部署描述符中可能包含的所有子元素。

注意:在Servlet 2.3中,子元素必須按照DTD檔案語法描述中指定的順序出現。比如:如果部署描述符中的<web-app>元素有<servlet>和<servlet-mapping>兩個子元素,則<servlet>子元素必須出現在<servlet-mapping>子元素之前。在Servlet2.4中,順序並不重要。

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

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> 

5.1<context-param>解釋:

<context-param>元素含有一對引數名和引數值,用作應用的Servlet上下文初始化引數,引數名在整個Web應用中必須是惟一的,在web應用的整個生命週期中上下文初始化引數都存在,任意的Servlet和jsp都可以隨時隨地訪問它。<param-name>子元素包含有引數名,而<param-value>子元素包含的是引數值。作為選擇,可用<description>子元素來描述引數。

5.2 什麼情況下使用,為什麼使用<context-param>:

比如:定義一個管理員email地址用來從程式傳送錯誤,或者與你整個應用程式有關的其他設定。使用自己定義的設定檔案需要額外的程式碼和管理;直接在你的程式中使用硬編碼(Hard-coding)引數值會給你之後修改程式帶來麻煩,更困難的是,要根據不同的部署使用不同的設定;通過這種辦法,可以讓其他開發人員更容易找到相關的引數,因為它是一個用於設定這種引數的標準位置。

5.3 Spring配置檔案:

配置Spring,必須需要<listener>,而<context-param>可有可無,如果在web.xml中不寫<context-param>配置資訊,預設的路徑是/WEB-INF/applicationontext.xml,在WEB-INF目錄下建立的xml檔案的名稱必須是applicationContext.xml。如果是要自定義檔名可以在web.xml里加入contextConfigLocation這個context引數:在<param-value>

</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 

就可以在執行時動態地找出專案的路徑。

5.4 多個配置檔案交叉引用處理:

如果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中。

5.5 在不同環境下如何獲取:範例:

<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");

Servlet的ServletConfig物件擁有該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>

7.1 Listener介紹:

<listener>為web應用程式定義監聽器,監聽器用來監聽各種事件,比如:application和session事件,所有的監聽器按照相同的方式定義,功能取決去它們各自實現的介面,常用的Web事件介面有如下幾個: (1). ServletContextListener:用於監聽Web應用的啟動和關閉; (2). ServletContextAttributeListener:用於監聽ServletContext範圍(application)內屬性的改變; (3). ServletRequestListener:用於監聽使用者的請求; (4). ServletRequestAttributeListener:用於監聽ServletRequest範圍(request)內屬性的改變; (5). HttpSessionListener:用於監聽使用者session的開始和結束; (6). HttpSessionAttributeListener:用於監聽HttpSession範圍(session)內屬性的改變。 <listener>主要用於監聽Web應用事件,其中有兩個比較重要的WEB應用事件:應用的啟動和停止(starting up or shutting downSession的建立和失效(created or destroyed。應用啟動事件發生在應用第一次被Servlet容器裝載和啟動的時候;停止事件發生在Web應用停止的時候。Session建立事件發生在每次一個新的session建立的時候,類似地Session失效事件發生在每次一個Session失效的時候。為了使用這些Web應用事件做些有用的事情,我們必須建立和使用一些特殊的“監聽類”。它們是實現了以下兩個介面中任何一個介面的簡單java類:javax.servlet.ServletContextListener或javax.servlet.http.HttpSessionListener,如果想讓你的類監聽應用的啟動和停止事件,你就得實現ServletContextListener介面;想讓你的類去監聽Session的建立和失效事件,那你就得實現HttpSessionListener介面。

7.2 Listener配置:

配置Listener只要向Web應用註冊Listener實現類即可,無序配置引數之類的東西,因為Listener獲取的是Web應用ServletContext(application)的配置引數。為Web應用配置Listener的兩種方式:

(1). 使用@WebListener修飾Listener實現類即可。

(2). 在web.xml文件中使用<listener>進行配置。

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

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

這裡的<listener>用於Spring的載入,Spring載入可以利用ServletContextListener實現,也可以採用load-on-startup Servlet 實現,但是當<filter>需要用到bean時,但載入順序是:先載入<filter>後加載<servlet>,則<filter>中初始化操作中的bean為null;所以,如果過濾器中要使用到bean,此時就可以根據載入順序<listener> -> <filter> -> <servlet>,將spring的載入改成Listener的方式。

(1). 利用ServletContextListener實現:

<servlet>    
   <servlet-name>context</servlet-narne>   
   <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>    
   <load-on-startup>1</load-on-startup>    
</servlet>

(2).採用load-on-startup Servlet 實現:

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

我們選擇了第二種方式,在J2EE工程中web伺服器啟動的時候最先呼叫web.xml,上面這段配置的意思是載入spring的監聽器,其中ContextLoaderListener的作用就是啟動Web容器時,自動裝配applicationContext.xml的配置資訊,執行它所實現的方法。

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>

8.1 Filter介紹:

Filter可認為是Servle的一種“加強版”,主要用於對使用者請求request進行預處理,也可以對Response進行後處理,是個典型的處理鏈。使用Filter的完整流程是:Filter對使用者請求進行預處理,接著將請求HttpServletRequest交給Servlet進行處理並生成響應,最後Filter再對伺服器響應HttpServletResponse進行後處理。Filter與Servlet具有完全相同的生命週期,且Filter也可以通過<init-param>來配置初始化引數,獲取Filter的初始化引數則使用FilterConfig的getInitParameter()。

換種說法,Servlet裡有request和response兩個物件,Filter能夠在一個request到達Servlet之前預處理request,也可以在離開Servlet時處理response,Filter其實是一個Servlet鏈。以下是Filter的一些常見應用場合,

(1)認證Filter

(2)日誌和稽核Filter

(3)圖片轉換Filter

(4)資料壓縮Filter

(5)密碼Filter

(6)令牌Filter

(7)觸發資源訪問事件的Filter

(8)XSLT Filter

(9)媒體型別鏈Filter

Filter可負責攔截多個請求或響應;一個請求或響應也可被多個Filter攔截。建立一個Filter只需兩步: (1) 建立Filter處理類 (2) Web.xml檔案中配置Filter Filter必須實現javax.servlet.Filter介面,在該介面中定義了三個方法: (1) void init(FilterConfig config):用於完成Filter的初始化。FilteConfig用於訪問Filter的配置資訊。 (2) void destroy():用於Filter銷燬前,完成某些資源的回收。 (3) void doFilter(ServletRequest request,ServletResponse response,FilterChain chain):實現過濾功能的核心方法,該方法就是對每個請求及響應增加額外的處理。該方法實現對使用者請求request進行預處理,也可以實現對伺服器響應response進行後處理---它們的分界線為是否呼叫了chain.doFilter(request,response),執行該方法之前,即對使用者請求request進行預處理,執行該方法之後,即對伺服器響應response進行後處理。

8.2 Filter配置:

Filter可認為是Servlet的“增強版”,因此Filter配置與Servlet的配置非常相似,需要配置兩部分:配置Filter名稱和Filter攔截器URL模式。區別在於Servlet通常只配置一個URL,而Filter可以同時配置多個請求的URL。配置Filter有兩種方式: (1). 在Filter類中通過Annotation進行配置。

(2). 在web.xml檔案中通過配置檔案進行配置。 我們使用的是web.xml這種配置方式,下面重點介紹<filter>內包含的一些元素。 <filter>用於指定Web容器中的過濾器,可包含<filter-name>、<filter-class>、<init-param>、<icon>、<display-name>、<description>。

(1).<filter-name>用來定義過濾器的名稱,該名稱在整個程式中都必須唯一。

(2).<filter-class>元素指定過濾器類的完全限定的名稱,即Filter的實現類。

(3). <init-param>為Filter配置引數,與<context-param>具有相同的元素描述符<param-name>和<param-value>。

(4). <filter-mapping>元素用來宣告Web應用中的過濾器對映,過濾器被對映到一個servlet或一個URL 模式。這個過濾器的<filter>和<filter-mapping>必須具有相同的<filter-name>,指定該Filter所攔截的URL。過濾是按照部署描述符的<filter-mapping>出現的順序執行的。

8.21 字符集過濾器

<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-mapping>  
    <filter-name>CharacterEncodingFilter</filter-name>  
    <url-pattern>/*</url-pattern>  
  </filter-mapping>

CharacterEncodingFilter類可以通過簡單配置來幫我們實現字符集轉換的功能,引數encoding用於指定編碼型別,引數forceEncoding設為true時,強制執行request.setCharacterEncoding(this.encoding)和reponse.setCharacterEncoding(this.encoding)中的方法。

8.22 快取控制

<filter>  
    <filter-name>NoCache Filter</filter-name>  
    <filter-class>com.yonyou.mcloud.cas.client.authentication.NoCacheFilter</filter-class>  
</filter>  
  <filter-mapping>  
<filter-name>NoCache Filter</filter-name>  
<!—表示對URL全部過濾-->  
    <url-pattern>/*</url-pattern>  
</filter-mapping>

8.23 登入認證

<!-- 認證過濾器 -->  
  <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>  
  <filter-mapping>  
     <filter-name>CAS Authentication Filter</filter-name>  
     <url-pattern>/*</url-pattern>  
  </filter-mapping>

登入認證,未登入使用者導向CAS Server進行認證。

8.24 單點登出

<filter>  
      <filter-name>CAS Single Sign Out Filter</filter-name>  
      <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>  
</filter>  
<filter-mapping>  
      <filter-name>CAS Single Sign Out Filter</filter-name>  
       <url-pattern>/*</url-pattern>  
</filter-mapping>  
<listener>  
      <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>  
</listener>

CAS Server通知CAS Client,刪除session,登出登入資訊。

8.25 封裝request

<filter>  
    <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
    <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>  
</filter>  
<filter-mapping>  
    <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
</filter-mapping>

封裝request, 支援getUserPrincipal等方法。

8.26 存放Assertion到ThreadLocal中

<filter>  
    <filter-name>CAS Assertion Thread Local Filter</filter-name>  
    <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>  
</filter>  
<filter-mapping>  
    <filter-name>CAS Assertion Thread Local Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
</filter-mapping>

8.27 禁用瀏覽器快取

<filter>  
    <filter-name>NoCache Filter</filter-name>  
    <filter-class>com.yonyou.mcloud.cas.client.authentication.NoCacheFilter</filter-class>  
 </filter>  
 <filter-mapping>  
    <filter-name>NoCache Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
 </filter-mapping>

8.28 CAS Client向CAS Server進行ticket驗證

<!-- 驗證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-mapping>  
    <filter-name>CAS Validation Filter</filter-name>  
    <url-pattern>/proxyCallback</url-pattern>  
</filter-mapping>  
<filter-mapping>  
    <filter-name>CAS Validation Filter</filter-name>  
    <url-pattern>/*</url-pattern>  
</filter-mapping>

9. <servlet></servlet>

<!--****************************servlet</span><span style="font-family:SimSun;">配置</span><span style="font-family:Times New Roman;">******************************-->  
<!-- Spring view</span><span style="font-family:SimSun;">分發器  對所有的請求都由business對應的類來控制轉發</span><span style="font-family:Times New Roman;"> -->  
<servlet>  
    <servlet-name>business</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    <init-param>  
      <param-name>publishContext</param-name>  
      <param-value>false</param-value>  
    </init-param>  
    <load-on-startup>1</load-on-startup>  
</servlet>  
<!-- </span><span style="font-family:SimSun;">使用者登出</span><span style="font-family:Times New Roman;"> -->  
<servlet>  
    <servlet-name>LogOutServlet</servlet-name>  
    <servlet-class>com.yonyou.mcloud.cas.web.servlet.LogOutServlet</servlet-class>  
    <init-param>  
      <param-name>serverLogoutUrl</param-name>  
      <param-value>https://dev.yonyou.com:443/sso-server/logout</param-value>  
    </init-param>  
    <init-param>  
      <param-name>serverName</param-name>  
      <param-value>http://10.1.215.40:80/business/</param-value>  
    </init-param>  
</servlet>  
<!--****************************servlet</span><span style="font-family:SimSun;">對映關係配置</span><span style="font-family:Times New Roman;">*************************-->  
<servlet-mapping>  
    <servlet-name>LogOutServlet</servlet-name>  
    <url-pattern>/logout</url-pattern>  
</servlet-mapping>  
<servlet-mapping>  
    <servlet-name>business</servlet-name>  
    <url-pattern>/</url-pattern>  
</servlet-mapping>

9.1 Servlet介紹:

Servlet通常稱為伺服器端小程式,是執行在伺服器端的程式,用於處理及響應客戶的請求。Servlet是個特殊的java類,繼承於HttpServlet。客戶端通常只有GET和POST兩種請求方式,Servlet為了響應則兩種請求,必須重寫doGet()和doPost()方法。大部分時候,Servlet對於所有的請求響應都是完全一樣的,此時只需要重寫service()方法即可響應客戶端的所有請求。

另外,HttpServlet有兩個方法:

(1). init(ServletConfig config):建立Servlet例項時,呼叫該方法的初始化Servlet資源。

(2). destroy():銷燬Servlet例項時,自動呼叫該方法的回收資源。

通常無需重寫init()和destroy()兩個方法,除非需要在初始化Servlet時,完成某些資源初始化的方法,才考慮重寫init()方法,如果重寫了init()方法,應在重寫該方法的第一行呼叫super.init(config),該方法將呼叫HttpServlet的init()方法。如果需要在銷燬Servlet之前,先完成某些資源的回收,比如關閉資料庫連線,才需要重寫destory方法()。

Servlet的生命週期:

建立Servlet例項有兩個時機:

(1). 客戶端第一次請求某個Servlet時,系統建立該Servlet的例項,大部分Servlet都是這種Servlet。

(2). Web應用啟動時立即建立Servlet例項,即load-on-start Servlet。

每個Servlet的執行都遵循如下生命週期:

(1). 建立Servlet例項。

(2). Web容器呼叫Servlet的init()方法,對Servlet進行初始化。

(3). Servlet初始化後,將一直存在於容器中,用於響應客戶端請求,如果客戶端傳送GET請求,容器呼叫Servlet的doGet()方法處理並響應請求;如果客戶端傳送POST請求,容器呼叫Servlet的doPost()方法處理並響應請求。或者統一使用service()方法處理來響應使用者請求。

(4). Web容器決定銷燬Servlet時,先呼叫Servlet的destory()方法,通常在關閉Web應用時銷燬Servlet例項。

9.2 Servlet配置:

為了讓Servlet能響應使用者請求,還必須將Servlet配置在web應用中,配置Servlet需要修改web.xml檔案。從Servlet3.0開始,配置Servlet有兩種方式:

(1). 在Servlet類中使用@WebServlet Annotation進行配置。

(2). 在web.xml檔案中進行配置。

我們用web.xml檔案來配置Servlet,需要配置<servlet>和<servlet-mapping>。<servlet>用來宣告一個Servlet。<icon>、<display-name>和<description>元素的用法和<filter>的用法相同。<init-param>元素與<context-param>元素具有相同的元素描述符,可以使用<init-param>子元素將初始化引數名和引數值傳遞給Servlet,訪問Servlet配置引數通過ServletConfig物件來完成,ServletConfig提供如下方法:

java.lang.String.getInitParameter(java.lang.String name):用於獲取初始化引數

ServletConfig獲取配置引數的方法和ServletContext獲取配置引數的方法完全一樣,只是ServletConfig是取得當前Servlet的配置引數,而ServletContext是獲取整個Web應用的配置引數。

(1). <description>、<display-name>和<icon>

1). <description>:為Servlet指定一個文字描述。

2). <display-name>:為Servlet提供一個簡短的名字被某些工具顯示。

3). <icon>:為Servlet指定一個圖示,在圖形管理工具中表示該Servlet。

(2). <servlet-name>、<servlet-class>和<jsp-file>元素

<servlet>必須含有<servlet-name>和<servlet-class>,或者<servlet-name>和<jsp-file>。 描述如下:

1). <servlet-name>用來定義servlet的名稱,該名稱在整個應用中必須是惟一的。

2). <servlet-class>用來指定servlet的完全限定的名稱。

3). <jsp-file>用來指定應用中JSP檔案的完整路徑。這個完整路徑必須由/開始。

(3). <load-on-startup>

如果load-on-startup元素存在,而且也指定了jsp-file元素,則JSP檔案會被重新編譯成Servlet,同時產生的Servlet也被載入記憶體。<load-on-startup>的內容可以為空,或者是一個整數。這個值表示由Web容器載入記憶體的順序。

舉個例子:如果有兩個Servlet元素都含有<load-on-startup>子元素,則<load-on-startup>子元素值較小的Servlet將先被載入。如果<load-on-startup>子元素值為空或負值,則由Web容器決定什麼時候載入Servlet。如果兩個Servlet的<load-on-startup>子元素值相同,則由Web容器決定先載入哪一個Servlet。<load-on-startup>1</load-on-startup>表示啟動容器時,初始化Servlet。

(4). <servlet-mapping>

<servlet-mapping>含有<servlet-name>和<url-pattern>

1). <servlet-name>:Servlet的名字,唯一性和一致性,與<servlet>元素中宣告的名字一致。

2). <url-pattern>:指定相對於Servlet的URL的路徑。該路徑相對於web應用程式上下文的根路徑。<servlet-mapping>將URL模式對映到某個Servlet,即該Servlet處理的URL。

(5). 載入Servlet的過程 

容器的Context物件對請求路徑(URL)做出處理,去掉請求URL的上下文路徑後,按路徑對映規則和Servlet對映路徑(<url- pattern>)做匹配,如果匹配成功,則呼叫這個Servlet處理請求。 

9.3DispatcherServlet在web.xml中的配置:

<!-- Spring view分發器  對所有的請求都由business對應的類來控制轉發 -->  
<servlet>  
    <servlet-name>business</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    <init-param>  
      <param-name>publishContext</param-name>  
      <param-value>false</param-value>  
    </init-param>  
    <load-on-startup>1</load-on-startup>  
</servlet>

配置Spring MVC,指定處理請求的Servlet,有兩種方式:

(1). 預設查詢MVC配置檔案的地址是:/WEB-INF/${servletName}-servlet.xml

(2). 可以通過配置修改MVC配置檔案的位置,需要在配置DispatcherServlet時指定MVC配置檔案的位置。

我們在平臺專案兩個工程中分別使用了不同的配置方式,介紹如下:

(1). 在business-client工程中按照預設方式查詢MVC的配置檔案,配置檔案目錄為: /WEB-INF/business-servlet.xml。工程目錄結構如下所示:

(2).在public-base-server工程中,通過第2種方式進行配置,把spring-servlet.xml放到src/main/resources/config/spring-servlet.xml,則需要在配置DispatcherServlet時指定<init-param>標籤。具體程式碼如下:

<servlet>  
    <servlet-name>spring</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
      <init-param>  
        <param-name>publishContext</param-name>  
        <param-value>false</param-value>  
</init-param>  
 <init-param>    
         <param-name>contextConfigLocation</param-name>    
            <param-value>classpath:config/spring-servlet.xml</param-value>    
        </init-param>   
     <load-on-startup>1</load-on-startup>  
</servlet>

工程目錄結構如下:

其中,classpath是web專案的類路徑,可以理解為classes下面。因為無論這些配置檔案放在哪,編譯之後如果沒有特殊情況的話都直接在classes下面。jar包的話雖然放在lib資料夾裡,但實際上那些類可以直接引用,比如:com.test.ABC,彷彿也在classes下面一樣。

在我們的工程裡,經過驗證,maven工程這兩個路徑經過編譯後生成的檔案都位於classes目錄下,即這兩個路徑相當於類路徑,在下面建立config資料夾(folder),然後建立自定義的xml配置檔案即可。

classpath和classpath*區別:同名資源存在時,classpath只從第一個符合條件的classpath中載入資源,而classpath*會從所有的classpath中載入符合條件的資源。classpath*,需要遍歷所有的classpath,效率肯定比不上classpath,因此在專案設計的初期就儘量規劃好資原始檔所在的路徑,避免使用classpath*來載入。

9.4 ContextLoaderListener和DispatcherServlet初始化上下文關係和區別:

從上圖可以看出,ContextLoaderListener初始化的上下文載入的Bean是對於整個應用程式共享的,一般如:DAO層、Service層Bean;DispatcherServlet初始化的上下文載入的Bean是隻對Spring MVC有效的Bean,如:Controller、HandlerMapping、HandlerAdapter等,該初始化上下文只加載Web相關元件。

注意:使用者可以配置多個DispatcherServlet來分別處理不同的url請求,每個DispatcherServlet上下文都對應一個自己的子Spring容器,他們都擁有相同的父Spring容器(業務層,持久(dao)bean所在的容器)。

10. <welcome-file-list></welcome-file-list>

<!-- welcome page -->  
<welcome-file-list>  
    <welcome-file>index.html</welcome-file>  
</welcome-file-list>

<welcome-file-list>包含一個子元素<welcome-file>,<welcome-file>用來指定首頁檔名稱。<welcome-file-list>元素可以包含一個或多個<welcome-file>子元素。如果在第一個<welcome-file>元素中沒有找到指定的檔案,Web容器就會嘗試顯示第二個,以此類推。

11. 參考文獻:

http://wiki.metawerx.net/wiki/Web.xml http://www.cnblogs.com/konbluesky/articles/1925295.html http://blog.csdn.net/sapphire_aling/article/details/6069764 http://blog.csdn.net/zndxlxm/article/details/8711626 http://blog.csdn.net/zhangliao613/article/details/6289114 http://www.cnblogs.com/bukudekong/archive/2011/12/26/2302081.html http://blog.sina.com.cn/s/blog_92b93d6f0100ypp9.html http://blog.csdn.net/heidan2006/article/details/3075730 http://zhidao.baidu.com/link?url=vBOBj5f2D1Zx3wSUJo-XphWrG6f7QPmfzk0UtS9Xk7p1SG_OdeCkiH6dT6eyHO-Pa6p4hLTEfvY7O9d_OM0Gua http://www.blogjava.net/dashi99/archive/2008/12/30/249207.html http://uule.iteye.com/blog/2051817 http://blog.csdn.net/javaer617/article/details/6432654 http://blog.csdn.net/seng3018/article/details/6758860 http://groups.tianya.cn/tribe/showArticle.jsp?groupId=185385&articleId=2704257273118260804105385 http://blog.csdn.net/qfs_v/article/details/2557128 http://www.blogjava.net/fancydeepin/archive/2013/03/30/java-ee_web-xml.html http://wenku.baidu.com/link?url=P30DokIynD5zzRU2dtdkQhEwsHi-REKuBiHa_dK60bA6pQwggvX2mo9y9Mbb1tkYcsiRCaHBf-c 4ZgIG5POmbbcRO_OxDJUaW15n300xJrq  http://fyq891014.blog.163.com/blog/static/200740191201233052531278/  http://blog.163.com/sir_876/blog/static/11705223201111544523333/  http://www.guoweiwei.com/archives/797  http://www.open-open.com/lib/view/open1402751642806.html  http://sishuok.com/forum/blogPost/list/5188.html;jsessionid=EBC2151611BEB99BDF390C5CADBA693A http://www.micmiu.com/j2ee/spring/spring-classpath-start/ http://elf8848.iteye.com/blog/2008595 http://blog.csdn.net/arvin_qx/article/details/6829873 輕量級javaEE企業應用實戰(第3版) ---李剛