2.12.2 Servlet3的Web模块支持

2.12.2 Servlet3的Web模块支持

Servlet3为模块化开发提供了良好的支持,Servlet3规范不再要求所有web组件(如ServletListenerFilter等)都部署在web.xml文件中,而是允许采用“web模块”来部署、管理它们。

Web模块结构

Web模块通常对应于一个JAR包,这个JAR包有如下文件结构:

1
2
3
4
<webModule>.jar——这是Web模块的JAR包,可以改变
├─META-INF
│ └─web-fragment.xml
└─Web模块所用的类文件、资源文件等

web模块部署描述符

从上面的文件结构可以看出,Web模块与普通JAR的最大区别在于需要在META-INF目录下添加个web-fragment.xml文件,这个文件也被称为web模块部署描述符。

web-fragment.xml文件与web.xml文件的作用、文档结构都基本相似,因为它们都用于部署、管理各种web组件。只是web-fragment.xml用于部署、管理web模块而已,但web-fragment.xml文件可以多指定如下两个元素:

  1. <name>:用于指定该Web模块的名称
  2. <ordering>:用于指定加载该Web模块的相对顺序。

上面<ordering>元素用于指定加载当前web模块的相对顺序,该元素的内部结构如图2.49所示。

程序示例

crazyit模块

下面开发第一个Web模块,该web模块内只定义了一个简单的ServletContextListner,该Web模块对应的web-fragment.xml文件如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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_3_1.xsd" version="3.1">
<!-- 指定该Web模块的唯一标识 -->
<name>crazyit</name>
<listener>
<listener-class>lee.CrazyitListener</listener-class>
</listener>
<ordering>
<!-- 用配置该Web模块必须位于哪些模块之前加载 -->
<before>
<!-- 用于指定位于其他所有模块之前加载 -->
<others/>
</before>
</ordering>
</web-fragment>

上面的web模块部署描述文件的根元素是<web-fragment>
代码:

1
<name>crazyit</name>

指定该Web模块的名称是crazyit,接下来代码:

1
2
3
4
5
6
7
<ordering>
<!-- 用配置该Web模块必须位于哪些模块之前加载 -->
<before>
<!-- 用于指定位于其他所有模块之前加载 -->
<others/>
</before>
</ordering>

指定该web模块将在其他所有web模块之前加载.

leegang模块

接下来再开发一个web模块,接下来的Web模块同样只定义了一个ServletContextListener,该Web模块对应的web-Fragment.xm文件如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="GBK"?>
<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_3_1.xsd" version="3.1">
<!-- 指定该Web模块的唯一标识 -->
<name>leegang</name>
<!-- 配置Listener -->
<listener>
<listener-class>lee.LeegangListener</listener-class>
</listener>
<ordering>
<!-- 用配置该Web模块必须位于哪些模块之后加载 -->
<after>
<!-- 此处可用多个name元素列出该模块必须位于这些模块之后加载 -->
<name>crazyit</name>
</after>
</ordering>
</web-fragment>

将这两个Web模块打包成JAR包,Web模块JAR包的内部结构如图2.50所示。
将这两个Web模块对应的JAR包复制到任意Web应用的WEBNF/lib目录下,启动Web应用,将可以看到两个Web模块被加载:先加载crazyit模块,再加载leegang模块。

web.xml中指定Web模块加载的绝对顺序

Web应用除了可按web-fragment.xml文件中指定的加载顺序来加载Web模块之外,还可以通过web.xml文件指定各Web模块加载的绝对顺序。在web.xml文件中指定的加载顺序将会覆盖Web模块中web-fragment.xml文件所指定的加载顺序.
假如在Web应用的web.xml文件中增加如下配置片段:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="GBK"?>
<web-app 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-app_3_1.xsd" version="3.1">
<absolute-ordering>
<!-- 指定Web模块按如下顺序加载 -->
<name>leegang</name>
<name>crazyit</name>
</absolute-ordering>
</web-app>

上面的配置片段指定了先加载leegang模块,后加载crazyit模块,如果重新启动该Web应用,将可看到leegang模块被优先加载

Web模块化开发的优点

Servlet3web模块支持为模块化开发、框架使用提供了巨大的方便,例如需要在web应用中使用web框架,这就只要将该框架的JAR包复制到Web应用中即可。因为这个JAR包的META-NF目录下可以通过web-fragment.xml文件来配置该框架所需的ServletListenerFilter等,从而避免修改Web应用的web.xml文件。Web模块支持对于模块化开发也有很大的帮助,开发者可以将不同模块的web组件部署在不同的web-fragment.xml文件中,从而避免所有模块的配置、部署信息都写在web.xml文件中,这对以后的升级、维护将更加方便。