很多Java Web应用都是基于某个框架的,如Apache Wicket、Java ServerFaces、Struts或是Spring MVC等等。要想使用框架,开发者需要在应用的web.xml配置文件中注册框架的切入代码,如Servlet、Filter或是Listener。这么做的后果就是部署描述符变得很庞大,同时导致框架所用的XML与特定于应用的XML混杂在了一起。Servlet 3.0规范的一个主要目标就是让开发者无需编辑web.xml部署描述符就能部署Servlet、Filter和Listener,同时可以将web.xml文件拆分成多个模块。为了实现这一点,Servlet 3.0规范增加了基于注解的配置(@WebServlet、@ServletFilter以及@WebServletContextListener),这使得我们可以不再需要web.xml文件,同时规范还引入了一个新的概念:Web片段(Web Fragment)。
Web片段可以将框架的“样板”XML与应用的其他配置分开,并且能够实现应用的自我注册。Web片段必须放在名为web-fragment.xml的文件中,该文件只要位于Web应用的classpath下即可,但通常都将其放到META-INF目录下或是框架的jar文件中。XML以<web-fragment>元素开始,里面包含的元素与web.xml部署描述符大同小异。如下代码所示:
<web-fragment>
<filter>
<filter-name>MyXSSFilter</filter-name>
<filter-class> MyXssFilter</filter-class>
</filter>
<servlet>
<servlet-name>myFrameworkServlet</servlet-name>
<servlet-class> MyFrameworkServlet</servlet-class>
</servlet>
<listener>
<listener-class> MyFrameworkListener</listener-class>
</listener>
</web-fragment>
容器在部署时会处理XML片段并组装成最终的部署描述符。由于容器负责组装web.xml文件,因此如果需要按照特定的顺序来调用框架的Servlet、Listener或Filter时就可能产生问题。为了避免这个问题,Servlet 3.0 API支持绝对与相对顺序的部署描述符。我们可以在web.xml文件中使用<absolute-ordering>元素指定绝对顺序,这样WEB-INF/lib下的每个jar都可以通过META-INF/web-fragment.xml文件的<name>元素获得一个名字。接下来,Web应用的WEB-INF/web.xml文件可以通过<absolute-ordering>元素按照顺序列举出这些片段名,这个顺序就是jar的调用顺序,同时还有一个可选的<others/>元素用于指定是否以及何时包含那些未命名的jar文件。由于部署者可以选择只列出那些受信任的jar以进行部署,这样就可以避免意外情况的发生。除此之外,通过顺序还可以排除那些不需要被扫描的jar,这样就可以加快应用的部署速度。最后,如果你不想在产品环境下看到自我注册的情况发生,那就可以在web.xml文件中使用<metadata-complete>元素,这会告诉Web容器只去寻找注解而非Web片段。
