基于多模块的maven项目
目前Java的开发基本都已经依赖于maven对项目进行构建和依赖管理。虽然gradle也逐渐被更多的人开始使用,但就目前来说maven的使用率还是比较高的。 并且,随着微服务的流行在maven的多模块的需求也逐渐增加,也同样能够提升maven工程的代码复用。所以,这里对于maven的多模块项目做一个配置相关的介绍。
多模块的简单介绍
maven作为一个用于管理项目依赖及构建的工具被广泛应用于java的工程中,同时被诸如Eclipse,IntelliJ IDEA等集成开发环境所支持。 采用maven的优势在于能够不依赖于开发环境对工程进行构建,并能对第三方依赖做统一的管理。而对于maven的多模块工程而言,能够提升工程代码的复用, 以及在微服务这类应用场景中,对各个微服务独立于maven仓库的支持作自定义包的使用。
这种应用场景下,maven工程由一个位于顶层目录的parent工程构成,各个子模块分别再其下进行生成。多模块项目中的模块也能够是一个多模块的项目。 在构建时,应该位于parent工程所在的目录执行maven命令。
根工程的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>xyz.bezalel.nebula</groupId>
<artifactId>parnet</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>
<modules>
<module>nebula-app</module>
<module>common</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
</project>
以上的配置文件定义了一个多模块的maven项目,注意作为根的pom.xml文件中,packaging标签所使用的是pom,而不是传统的jar或者war等。 同时,在配置文件中定义了其有两个子模块nebula-app与common。而在根工程中所定义的对lombok的依赖,将被其子工程所继承。
子模块的pom.xml文件
在之parent的pom.xml文件所在的目录下,新建nebula-app与common目录作为其子工程所在的文件夹。
common模块的pom.xml文件
以下为common工程目录内的pom.xml配置文件,由于其继承于xyz.bezalel.nebula,因此其groupId可以省略。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parnet</artifactId>
<groupId>xyz.bezalel.nebula</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common</artifactId>
</project>
nebula-app模块的pom.xml文件
以下为nebula工程目录内的pom.xml配置文件,根据定义其依赖于另一个common模块,此处需要按照标准的第三方包的方式定义其依赖模块。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parnet</artifactId>
<groupId>xyz.bezalel.nebula</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nebula-app</artifactId>
<dependencies>
<dependency>
<groupId>xyz.bezalel.nebula</groupId>
<artifactId>common</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
多模块的maven项目编译与打包
对于编译与打包,需要在parent的pom.xml文件所在的目录下,执行maven命令。
mvn clean compile package
针对spring boot的多模块项目
由于maven的项目结构是一个树的结构,因此maven项目不能有多个parent。因此,spring boot的根工程pom.xml需要设置其parent为 spring-boot-starter-parent。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>xyz.bezalel.nebula</groupId>
<artifactId>parnet</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>
<modules>
<module>nebula-app</module>
<module>common</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
</project>
而对于其子模块中,如果不需要打包的模块,则不需要添加对应的spring-boot-maven-plugin,只有需要将其打包成jar执行的包才需要。 例如本示例中的nebula-app需要打包成可执行的jar文件,则其配置文件如下。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parnet</artifactId>
<groupId>xyz.bezalel.nebula</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nebula-app</artifactId>
<dependencies>
<dependency>
<groupId>xyz.bezalel.nebula</groupId>
<artifactId>common</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
总结及说明
对于maven来说xml的编写的确很繁琐且冗余,xml格式的情况着实有些尴尬。相比于诸如bson等二进制数据,它的可读性的确提高了, 但相应的体积也解析复杂度也提高,而与toml或者json等数据格式比较,xml的可读性又显得累赘,而且解析速度也是toml这些更高。 所以,xml着实位于一个高不成低不就的位置。
对于spring boot的多模块项目,原本使用 spring-boot:run 可以执行,但现在由于其依赖问题将不能执行了。虽然有其他资料声称,对parent 工程执行mvn install可以解决,但这样做是把你的工程安装到本地的仓库中,如此而行的结果是:你调试时执行的代码与你编写的代码可能不是一个。 意思就是,你调试时调用的是你位于本地仓库中之前install的工程,而你修改后的内容由于没有被install,所以可能不会被执行。 因此,对于spring boot的各个应用,在继承开发环境中需要以普通的Java应用来执行,而不能通过maven的spring-boot:run来执行。