maven合并war包
在使用Maven分模块进行开发时,模块间必然存在相互依赖的关系。简单的以控制层web、业务层service、数据层dao三层划分为例,此时的模块结构可能如图所示。
pro-web模块依赖于pro-service模块,pro-web只负责接收、响应用户的请求,具体的业务逻辑交由pro-service进行处理。同一项目下的模块依赖,直接引入即可。
pro-web : pom.xml
<dependency>
<groupId>org.pro</groupId>
<artifactId>pro-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
同理,实际的数据访问经由业务层中转调用,由pro-dao连接数据库操作;那么pro-service模块依赖于pro-dao模块,直接在pro-service中引入pro-dao。
pro-service : pom.xml
<dependency>
<groupId>org.pro</groupId>
<artifactId>pro-dao</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
之后如果对pro-web模块进行打包,生成的war文件里将会包含了pro-service和pro-dao的jar文件。但是在实际开发中,模块的划分并不会永远都是那么简单;有时为了满足某些需求,可能存在多个web模块的情况。
例如在pro-web模块过于臃肿时想要分离静态资源到独立的模块,将原先的pro-web划分成了pro-web-1、pro-web-2两个部分。此时pro-web-1、pro-web-2之间显然不能靠简单的dependency依赖关系进行关联。
事实上不论基于何种理由,这种由多个war模块共同组成一个完整的war包对外服务的情景并不少见。
我遇到过类似的需求是在pro-web-1的基础上开发新的独立版本pro-web-2(2个版本独立部署互不干扰),而pro-web-2与pro-web-1的源码超过八成相同;并且在进行版本升级的时候,2个版本需要同时进行相同的功能升级。
此时如果从pro-web-1模块中复制一份源码文件,命名为pro-web-2并在这上面直接修改源代码,这是可以满足需求的。但是考虑到后期的代码维护成本,这却并不是一个好的方法,毕竟谁也不能保证是否会再增加新的版本pro-web-3、pro-web-4。
一个比较有效的方法就是在pro-web-2中只包含新增、修改的文件,其余相同的文件存留在pro-web-1模块中,对pro-web-2进行打包时,合并pro-web-1的war包。
1、合并war包
pro-web-2的war包想要合并pro-web-1的war包,首先是要获得pro-web-1的内容。dependency不指定类型时默认为导入jar包依赖,如果要依赖于war包,直接指定dependency的类型type为war即可。
pro-web-2 : pom.xml
<dependency>
<groupId>org.pro</groupId>
<artifactId>pro-web-1</artifactId>
<version>1.0-SNAPSHOT</version>
<type>war</type>
</dependency>
第二步就是对两者进行合并了,合并war包直接使用maven-war-plugin插件的overlay就能实现。
pro-web-2 : pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<overlays>
<overlay>
<groupId>org.pro</groupId>
<artifactId>pro-web-1</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
需要注意的是,打包时将会把pro-web-1的内容复制到pro-web-2的war包中,但是已存在的文件是会被跳过的,换个说法就是pro-web-2的文件将会覆盖pro-web-1的同名文件。
假定pro-web-1包中有与pro-web-2中相同的文件B
合并后得到的war包中新增了pro-web-1的文件,但是 文件B 依然是pro-web-2原先的那个文件
2、war包相互调用(交叉依赖)
简单的静态资源war包动态资源的war包进行合并,可能进行上面的步骤就已经完成了。但是当pro-web-2的某些class文件依赖于pro-web-1的class时,会在编译时因为找不到依赖的class而报错导致后续操作中断。
此时可以考虑在对pro-web-1进行打包的同时生成jar包,pro-web-2在编译时依赖于pro-web-1的jar,在编译完成后再对2个war包进行合并。
需要在打包时同时生成jar,借助maven-war-plugin插件即可实现
pro-web-1 : pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- 把JAR文件和标准的WAR文件同时安装到Maven仓库中 -->
<attachClasses>true</attachClasses>
</configuration>
</plugin>
而因为pro-web-1会生成jar包,所以pro-web-2可以直接引入依赖。这里需要注意的是,因为这个依赖只在编译时需要(打包完成后合并了2个war包,这些编译时找不到的class文件实际是存在的),所以这里引入的pro-web-1依赖指定编译时有效。
pro-web-2 : pom.xml
<dependency>
<groupId>org.pro</groupId>
<artifactId>pro-web-1</artifactId>
<version>1.0-SNAPSHOT</version>
<type>war</type>
</dependency>
<!-- 引入pro-web-1的jar -->
<dependency>
<groupId>org.pro</groupId>
<artifactId>pro-web-1</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 依赖类型为jar(没有声明时默认也是jar) -->
<type>jar</type>
<!-- 同时存在war和jar两个版本,需要进行区分,否则会找不到jar文件 -->
<classifier>classes</classifier>
<!-- 有效范围为编译期间 -->
<scope>provided</scope>
</dependency>
上一篇: 自定义Partitioner分区
下一篇: 使用ant打包WAR,超详细教程