如果說 3.0 版本新增的注解支持是為了簡化 Servlet/ 過濾器 / 監聽器的聲明,使得 web.xml 變為可選配置,新增的可插性 (pluggability) 支持則將 Servlet 配置的靈活性提升到了新的高度。使用該特性,現在我們可以在不修改已有 Web 應用的前提下,只需將按照一定格式打成的 JAR 包放到 WEB-INF/lib 目錄下,即可實現新功能的擴充,不需要額外的配置。
Servlet 3.0 引入了稱之為“Web 模塊部署描述符片段”的 web-fragment.xml 部署描述文件,該文件必須存放在 JAR 文件的 META-INF 目錄下,該部署描述文件可以包含一切可以在 web.xml 中定義的內容。AR 包通常放在 WEB-INF/lib 目錄下,除此之外,所有該模塊使用的資源,包括 class 文件、配置文件等,只需要能夠被容器的類加載器鏈加載的路徑上,比如 classes 目錄等。
現在為一個 Web 應用增加一個 Servlet 配置有三種方式:
- 編寫一個類繼承自 HttpServlet,將該類放在 classes 目錄下的對應包結構中,修改 web.xml,在其中增加一個 Servlet 聲明。這是最原始的方式;
- 編寫一個類繼承自 HttpServlet,并且在該類上使用 @WebServlet 注解將該類聲明為 Servlet,將該類放在 classes 目錄下的對應包結構中,無需修改 web.xml 文件。
- 編寫一個類繼承自 HttpServlet,將該類打成 JAR 包,并且在 JAR 包的 META-INF 目錄下放置一個 web-fragment.xml 文件,該文件中聲明了相應的 Servlet 配置。
web-fragment的示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment
xmlns=http://java.sun.com/xml/ns/javaee
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
metadata-complete="true">
<servlet>
<servlet-name>fragment</servlet-name>
<servlet-class>footmark.servlet.FragmentServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>fragment</servlet-name>
<url-pattern>/fragment</url-pattern>
</servlet-mapping>
</web-fragment>
由于一個 Web 應用中可以出現多個 web-fragment.xml 聲明文件,加上一個 web.xml 文件,加載順序問題便成了不得不面對的問題。需要時可以定義加載順序的規則。
web-fragment.xml 包含了兩個可選的頂層標簽,<name> 和 <ordering>,如果希望為當前的文件指定明確的加載順序,通常需要使用這兩個標簽,<name> 主要用于標識當前的文件,而 <ordering> 則用于指定先后順序。一個簡單的示例如下:
<web-fragment...>
<name>FragmentA</name>
<ordering>
<after>
<name>FragmentB</name>
<name>FragmentC</name>
</after>
<before>
<others/>
</before>
</ordering>
...
</web-fragment>
<name> 標簽的取值通常是被其它 web-fragment.xml 文件在定義先后順序時引用的,在當前文件中一般用不著,它起著標識當前文件的作用。
<ordering> 標簽內部,可以定義當前 web-fragment.xml 文件與其他文件的相對位置關系,這主要通過 <ordering> 的 <after> 和 <before> 子標簽來實現的。在這兩個子標簽內部可以通過 <name> 標簽來指定相對應的文件。比如:
<after>
<name>FragmentB</name>
<name>FragmentC</name>
</after>
以上片段表示當前文件必須在 FragmentB 和 FragmentC 之后解析。<before> 的使用與此相同,它所表示的是當前文件必須早于 <before> 標簽里所列出的 web-fragment.xml 文件。
除了將所比較的文件通過 <name> 在 <after> 和 <begin> 中列出之外,Servlet 還提供了一個簡化的標簽 <others/>。表示除了當前文件之外的其他所有的 web-fragment.xml 文件。該標簽的優先級要低于使用 <name> 明確指定的相對位置關系。