web.xml詳解

五月的倉頡發表於2015-11-03

web.xml的作用

web.xml,一個Tomcat工程中最重要的配置檔案。web.xml沒有其實也可以----只要你確定你的專案裡面不需要任何過濾器、監聽器、Servlet等等。我試了一下,沒有web.xml對那些已經編譯成Servlet的jsp頁面來說,是不影響正常顯示的,但是那些沒有編譯成Servlet的jsp頁面,訪問的時候就會報500的錯誤了。下面逐一看一下web.xml裡常用標籤的作用。

 

welcome-file-list

這個標籤是用來配置首頁用的:

<welcome-file-list>
    <welcome-file>index1.jsp</welcome-file>
    <welcome-file>index2.jsp</welcome-file>
    <welcome-file>index3.jsp</welcome-file>
    <welcome-file>index4.jsp</welcome-file>
    <welcome-file>/target/redirectAndFoward.jsp</welcome-file>
</welcome-file-list>

這麼配置的意思,就是當使用者訪問http://ip:port/工程名的時候,會根據welcome-file-list配置的頁面列表,從專案的根目錄開始找頁面:

1、第一個配置的index1.jsp能找到,就展示index1.jsp

2、找不到index1.jsp,則去找第二個index2.jsp,index2.jsp能找到就展示index2.jsp,

3、找不到index3.jsp,則去找第三個index3.jsp,以此類推,如果所有的頁面都找不到則報HTTP Status 404即頁面找不到

注意一下,像配置的最後一個welcome-file這種寫法也是支援的,我試了一下最前面的那個"/"可加可不加

 

error-page

error-page表示當HTTP返回指定狀態碼的時候,容器將此次請求轉發到配置的指定頁面: 

<error-page>
    <error-code>400</error-code>
    <location>/filter/error.jsp</location>
</error-page>
  
<error-page>
    <error-code>404</error-code>
    <location>/filter/error.jsp</location>
</error-page>
  
<error-page>
    <error-code>500</error-code>
    <location>/filter/error.jsp</location>
</error-page>

這表示HTTP狀態碼為400、404、500的時候,此次請求都會被轉發到http://ip:port/工程名/filter/error.jsp這個頁面上去。注意一下這裡是error-code,所以如果是200的話,是沒有效果的

 

filter

filter就不說了,兩種include方式及filter中的dispatcher解析一文已經講得很詳細了,filter的寫法也在上面。

另外注意一點,其實大家也都知道,提一下:filter執行的順序就是filter定義的順序

 

servlet

servlet開發者比較熟悉,先匹配規則,匹配到路徑後走相應的Servlet類,就不說了。下面配一個相對不那麼常用的,只是相對而已,這種servlet的寫法很常見:

<servlet>
    <servlet-name>startUpServlet</servlet-name>
    <servlet-class>com.xrq.servlet.StartUpServlet</servlet-class>
    <init-param>
        <param-name>Name</param-name>
        <param-value>123</param-value>
    </init-param>
    <init-param>
        <param-name>Age</param-name>
        <param-value>456</param-value>
    </init-param>
    <load-on-startup>8</load-on-startup>
</servlet>

這是一個啟動servlet,表示容器啟動的時候servlet啟動,呼叫其init()方法,所以首先第一個標籤load-on-start,分幾點說:

1、load-on-startup元素標記容器是否在啟動的時候就載入這個servlet(例項化並呼叫其init方法)

2、它的值必須是一個整數,表示servlet應該被載入的順序

3、當值為0或者大於0時,表示容器在應用啟動時就載入並初始化這個servlet

4、當值小於0或者沒有指定時,表示這個容器在該servlet被選擇時才會去載入

5、正數值越小,該servlet的優先順序就越高,應用啟動時就越先載入

6、當值相同時,容器自己選擇順序來載入

所以,load-on-startup中配置了一個大於等於0的正整數時,該servlet可以當作一個普通的servlet來用,無非是這個servlet啟動的時候會載入其init()方法罷了。

另外一個就是init-param了,表示一個鍵值對,只能在本servlet裡面被使用,通過ServletConfig獲取,StartUpServlet的寫法是:

public class StartUpServlet extends HttpServlet
{
    /**
     * 序列化
     */
    private static final long serialVersionUID = 1L;
    
    public void init() throws ServletException
    {
        System.out.println("StartUpServlet.init()");
        System.out.println("Name:" + getServletConfig().getInitParameter("Name"));
        System.out.println("Age:" + getServletConfig().getInitParameter("Age"));
    }
    
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
        
    }
    
    public void destroy()
    {
        System.out.println("StartUpServlet.destory()");
    }
}

servlet只能取到配置在自己的<servlet>標籤內的<init-param>。

 

listener

listener即監聽器,是Servlet的監聽器,它可以監聽客戶端的請求、伺服器端的操作等,在事情發生前後做一些必要的處理。通過監聽器,可以自動激發一些操作,比如監聽線上使用者數量,下面就寫一個監聽使用者數量的監聽器,首先web.xml配置很簡單:

<listener>
    <listener-class>com.xrq.listener.UserCounterListener</listener-class>
</listener>

寫一個監聽器,監聽使用者數量一般都是以session建立和session失效為依據的,所以實現HttpSessionListener:

public class UserCounterListener implements HttpSessionListener
{
    private AtomicInteger ai = new AtomicInteger(0);
    
    public void sessionCreated(HttpSessionEvent se)
    {
        ai.incrementAndGet();
    }
    
    public void sessionDestroyed(HttpSessionEvent se)
    {
        ai.decrementAndGet();
    }
    
    public int getUserCount()
    {
        return ai.get();
    }
}

除了監聽session的監聽器外,再介紹一些別的監聽器介面:

1、ServletContextListener

用於監聽WEB引用啟動和銷燬的事件,SevletContextListener是ServletContext的監聽者,如果ServletContext發生變化,如伺服器啟動、伺服器關閉,都會被ServletContextListener監聽到。監聽事件為ServletContextEvent

2、ServletContextAttributeListener

用於監聽WEB應用屬性改變的事件,包括新增屬性、刪除屬性、修改屬性。監聽時間為ServletContextAttributeEvent

3、HttpSessionBindingListener

HttpSessionBindingListener是唯一一個不需要在web.xml中配置的Listener,當我們的類實現了HttpSessionBindListener介面後,只要物件加入session或者從session中移除,容器會分別自動呼叫以下兩個方法:

(1)void valueBound(HttpSesssionBindEvent event)

(2)void valueUnbound(HttpSessionBindingEvent event)

注意,這個監聽器的觸發是針對於實現了該監聽器的類的,只有把實現了該監聽器的類set進session或從session中remove才會觸發這個監聽器

4、HttpSessionAttributeListener

用於監聽HttpSession中的屬性的操作,當session裡面增加一個屬性時,觸發attributeAdded(HttpSessionBindEvent se)方法;當在session中刪除一個屬性時,觸發attributeRemoved(HttpSessionBindEvent se)方法;當session屬性被重新設定時,觸發attributeReplaced(HttpSessionBindingEvent se)方法。

注意,這個監聽器的觸發是針對所有的session的,只要session的屬性發生變化,都會觸發這個監聽器

5、HttpSessionListener

這個上面已經寫過了,監聽HttpSession。當建立一個session時,觸發sessionCreated(HttpSessionEvent se)方法;當銷燬一個session時,會觸發sessionDestoryed(HttpSessionEvent se)方法

6、HttpSessionActivationListener

這個用得不太多,主要監聽同一個session轉移至不同的JVM的情形

7、ServletRequestListener和ServletRequestAttributeListener

和ServletContextListener和ServletContextAttributeListener類似,前者監聽Request的建立和銷燬、後者監聽Request中屬性的增刪改

 

context-param

context-param裡面配置的鍵值對是全域性共享的,整個web專案都能取到這個上下文,比方說我在web.xml裡面配置了一個HTTP埠和一個HTTPS埠:

<context-param>
    <param-name>NotSSLPort</param-name>
    <param-value>8080</param-value>
</context-param>
<context-param>
    <param-name>SSLPort</param-name>
    <param-value>8443</param-value>
</context-param>

servlet可以這麼取:

protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
{
    System.out.println("NotSSLPort:" + getServletContext().getInitParameter("NotSSLPort"));
    System.out.println("SSLPort:" + getServletContext().getInitParameter("SSLPort"));
}

filter可以這麼取:

public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException
{
    HttpServletRequest req = (HttpServletRequest)request;
    ServletContext sc = req.getSession().getServletContext();
    System.out.println("NotSSLPort:" + sc.getInitParameter("NotSSLPort"));
    System.out.println("SSLPort:" + sc.getInitParameter("SSLPort"));
    chain.doFilter(request, response);
}

listener可以這麼取,以ServletContextListener為例:

public void contextInitialized(ServletContextEvent sce)
{
    System.out.println("Enter SCListener.contextInitialized");
    System.out.println("NotSSLPort:" + sce.getServletContext().getInitParameter("NotSSLPort"));
    System.out.println("SSLPort:" + sce.getServletContext().getInitParameter("SSLPort"));
}

反正最終的目的就是取到一個ServletContext就對了。是不是感覺ServletContext很熟悉呢?沒錯,看一下jsp預設的內建物件,隨便開啟一個轉換成Servlet的jsp頁面,裡面都有內建物件的定義:

PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;

ServletContext也就是我們常說的Application

 

<mime-mapping>

<mime-mapping>可能不太常見,這個標籤是用來指定對應的格式的瀏覽器處理方式的,新增mime-type的對映,就可以避免某些型別的檔案直接在瀏覽器中開啟了。

舉個例子:

<mime-mapping>
    <extension>doc</extension>
    <mime-type>application/msword</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>pdf</extension>
    <mime-type>application/pdf</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>rar</extension>
    <mime-type>application/x-rar-compressed</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>txt</extension>
    <mime-type>text/plain</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>xls</extension>
    <mime-type>application/vnd.ms-excel</mime-type>
</mime-mapping>

這就指定了.doc、pdf、rar、txt、xls這五種型別的檔案的開啟方式了。常見的MIME型別有:

類  型 後  綴 MIME型別
超文字標記語言文字 .htm、.html text/html
普通文字 .txt text/plain
RFT文字 .rtf application/rtf
GIF圖形 .gif image/gif
JPEG圖形 .jpg、.jpeg image/jpeg
au聲音檔案 .au audio/basic
MIDI音樂檔案 .mid、.midi audio/midi、audio/x-midi
RealAudio音樂檔案 .ra、.ram audio/x-pn-realaudio
MPEG檔案 .mpg、.mpeg video/mpeg
AVI檔案 .avi video/x-msvideo
GZIP檔案 .gz application/x-gzip
TAR檔案 .tar application/x-tar

 

session-config

session-config是用來配置session失效時間的,因為session-config裡面只有一個子標籤:

<session-config>
    <session-timeout>30</session-timeout>
</session-config>

以分鐘為單位。當然,程式碼裡面也可以設定:

"request.getSession.setMaxInactiveInterval(30 * 60);"就可以了,單位為秒。

 

元素載入順序

首先可以肯定,載入順序與它們在web.xml檔案中的先後順序無關,即不會因為filter寫在listener前面就先載入filter。最終得出的結論是listener->filter->servlet。

然後是context-param,用於向ServletContext提供鍵值對,即應用程式上下文資訊,listener、filter、servlet都可能會用到這些上下文中的資訊,那麼context-param是否應該寫在listener、filter、servlet前面呢?未必,context-param可以寫在任何位置,因此真正的載入順序應該是:context-param->listener->filter->servlet

相關文章