在 Servlet 3.0 之後,可以使用標註來設定 Servlet 的相關資訊,實際上,Web 容器並不僅讀取 /WEB-INF/classes 中的 Servlet 標註訊息,如果一個 JAR 檔案中有使用標註的 Servlet,Web 容器也可以讀取標註資訊、載入類別並註冊為 Servlet 進行服務。
實際上,在 Servlet 3.0 之後,一個 JAR 檔案確實可以當作一個 Web 應用程式的部份模組,就如上面所說明的,事實上不僅是 Servlet,傾聽器、過濾器等,也可以在撰寫、 定義標註完畢後,封裝在 JAR 檔案中,視需要放置至 Web 應用程式的 /WEB-INF/lib 之中,以增減 Web 應用程式的功能性。
一個 JAR 檔案中,除了可使用標註定義的 Servlet、傾聽器、過濾器之外,也可以擁有自己的部署描述檔,這個檔案的名稱是 web-fragment.xml,必須放置在 JAR 檔案中的 META-INF 目錄之中,基本上,web.xml 中可定義的元素,在 web-fragment.xml 中也可以定義,舉個例子來說,你可以在 web-fragment.xml 中定義如下的內容:
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-fragment_4_0.xsd" version="4.0">
<name>WebFragment1</name>
<servlet>
<servlet-name>helloworld</servlet-name>
<servlet-class>cc.openhome.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloworld</servlet-name>
<url-pattern>/helloworld.view</url-pattern>
</servlet-mapping>
</web-fragment>
注意到 web-fragment.xml 的根標籤是 <web-fragment>
而不是 <web-app>
。實際上,web-fragment.xml 中所指定的類別,不一定要在 JAR 檔案中,也可以是在 web 應用程式的 /WEB-INF/classes 中。
Servlet 對 web.xml 與標註的配置順序並沒有定義,對 web-fragment.xml 及標註的配置順序也沒有定義,然而你可以決定 web.xml 與 web-fragment.xml 的配置順序,其中一個設定方式是在 web.xml 中使用 <absolute-ordering>
定義絕對順序。例如在 web.xml 中定義:
<web-app ...>
<absolute-ordering>
<name>WebFragment1</name>
<name>WebFragment2</name>
</absolute-ordering>
...
</web-app>
各個 JAR 檔中 web-fragment.xml 所定義的名稱不得重複,若有重複,則會忽略掉重複的名稱。另一個方式,是直接在每個 JAR 檔的 web-fragment.xml 中使用 <ordering>
,在其中使用 <before>
或 <after>
來定義順序。以下多個 web-fragment.xml 例子:
web-fragment.xml
<web-fragment ...>
<name>WebFragment1</name>
<ordering>
<after><name>MyFragment2</name>
</after></ordering>
...
</web-fragment>
web-fragment.xml
<web-fragment ...>
<name>WebFragment2</name>
..
</web-fragment>
web-fragment.xml
<web-fragment ...>
<name>WebFragment3</name>
<ordering>
<before><others/></before>
</ordering>
..
</web-fragment>
則載入定義的順序是 web.xml、WebFragment3、WebFragment2、WebFragment1。
如果將 web.xml 中 <web-app>
的 metadata-complete
屬性設定為 true
(預設是 false
),則表示 web.xml 中已完成 Web 應用程式的相關定義,部署時將不會掃描標註與 web-fragment.xml 中的定義,如果有 <absolute-ordering>
與 <ordering>
也會被忽略。例如:
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
metadata-complete="true" version="4.0">
...
</web-app>
如果 web-fragment.xml 中指定的類別可以在 web 應用程式的 /WEB-INF/classes 中找到,就會使用該類別,要注意的是,如果該類別本身有標註,而 web-fragment.xml 又有定義該類別為Servlet,則此時會有兩個 Servlet 實例。如果將 <web-fragment>
的 metadata-complete
屬性設定為 true
(預設是 false
),則就只會處理自己 JAR 檔案中的標註資訊。
你可以參考 Servlet 規格書內容,當中有更多的 web.xml、web-fragment.xml 的定義範例。