本文使用intellij idea
搭建Maven3
多模块项目,并进行配置相关配置,以实现项目的构建打包。
multi-module-project
是我们的项目名称,其中包含多个模块:
mmp-dal
模块:数据访问层,提供对原始数据(主要指数据库)的操作mmp-integration
模块:提供对第三方服务的调用mmp-commons
模块:提供工具类、常量定义等公共服务mmp-biz
模块:使用以上模块完成相关业务mmp-service
模块:对业务模块相应接口进行包装,并进行入参与返回值判断mmp-api
模块:提供对外服务的接口新建项目,选择Maven
,不要勾选Create from archetype
。
填写GroupId
、ArtifactId
与Version
。
GroupId
定义了项目属于哪个组,一般和项目所在的组织或公司存在关联ArtifactId
定义了当前Maven
项目在组中唯一的ID
Version
指定了项目当前的版本,SNAPSHOT
意为快照,说明该项目还处于开发中,是不稳定版本下面的Project name
与Project location
默认是没有-
的,这里我们为了与前面ArtifactId
一致,将-
加上。
由于multi-module-project
为聚合项目,因此我们删除src
文件夹。
接下来我们给该项目添加模块。
首先添加mmp-dal
模块。
和上面一样,这里我们为了与前面ArtifactId
一致,将-
加上。
依次添加各个模块。
下面multi-module-project
的POM
配置是idea
自动生成的,其中的注释解释了各个参数的含义。
<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.0modelVersion>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>multi-module-projectartifactId>
<packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<modules>
<module>mmp-dalmodule>
<module>mmp-integrationmodule>
<module>mmp-commonsmodule>
<module>mmp-bizmodule>
<module>mmp-servicemodule>
<module>mmp-apimodule>
modules>
project>
下面mmp-dal
的POM
配置同样由idea
自动生成,我们通过注释对各个参数进行说明。
<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>multi-module-projectartifactId>
<groupId>com.sigalhu.mmpgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>mmp-dalartifactId>
project>
项目搭建好后,我们先来配置一下测试依赖,在multi-module-project
的POM
中添加配置,这里由于篇幅所限,省略了之前已经提到的配置。
在配置依赖时,我们一般在父模块的dependencyManagement
中进行声明,此时声明的依赖并未生效,同时在properties
中定义一个表示版本号的Maven
属性,并通过${...}
加以引用,在以后当我们想要升级依赖的版本时,只需要修改properties
就可以。
接下来,我们通过dependencies
来引入项目依赖,由于junit
的依赖信息已经在dependencyManagement
中声明过了,所以我们只需要在dependencies
中声明junit
的groupId
和artifactId
,Maven
就会找到在dependencyManagement
中的对应声明并引用该依赖。
通过dependencies
引入的依赖会作用于当前项目以及在modules
中声明的子模块,这里所有子模块都要使用junit
进行单元测试,因此在父模块中引用该依赖。
<project>
...
<properties>
<junit.version>4.12junit.version>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
<scope>testscope>
dependency>
dependencies>
dependencyManagement>
project>
根据最开始的项目结构,我们知道该项目各个子模块之间也是存在依赖关系的,首先在multi-module-project
的POM
中声明各个子模块,其中project.version
是Maven
的默认属性,表示当前项目的版本。
<project>
...
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-apiartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-bizartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-commonsartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-dalartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-integrationartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-serviceartifactId>
<version>${project.version}version>
dependency>
dependencies>
dependencyManagement>
project>
mmp-biz
模块依赖mmp-dal
模块、mmp-integration
模块与mmp-commons
模块,因此在mmp-biz
模块的POM
中声明依赖。
<project>
...
<dependencies>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-dalartifactId>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-integrationartifactId>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-commonsartifactId>
dependency>
dependencies>
project>
同理,在mmp-service
模块的POM
中声明对mmp-biz
模块的依赖。
<project>
...
<dependencies>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-bizartifactId>
dependency>
dependencies>
project>
在mmp-api
模块的POM
中声明对mmp-service
模块的依赖。
<project>
...
<dependencies>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-serviceartifactId>
dependency>
dependencies>
project>
首先说一下思路,当我们完成开发后,需要将各个子模块打包,并与各个子模块的依赖、配置文件、启动脚本一起上传到服务器,以完成项目的部署。在这里,我们使用maven-dependency-plugin
来拷贝各个模块的依赖,使用maven-assembly-plugin
来对整个项目进行打包,而各子模块使用Maven
默认配置进行打包。
为了降低耦合度,我们在multi-module-project
下新建mmp-assembly
模块以负责打包任务,新建模块流程同上,需要注意的是,根据前面说过的构建过程,必须把mmp-assembly
模块放在modules
的最后一个,让该模块最后构建,因为该模块是用来打包整个项目的。
<project>
...
<modules>
<module>mmp-dalmodule>
<module>mmp-integrationmodule>
<module>mmp-commonsmodule>
<module>mmp-bizmodule>
<module>mmp-servicemodule>
<module>mmp-apimodule>
<module>mmp-assemblymodule>
modules>
...
project>
我们先使用maven-dependency-plugin
将各个子模块的依赖拷贝到mmp-assembly
模块的打包路径,具体配置如下,我们在build
的plugins
下声明插件。
需要说明的是,maven-dependency-plugin
和其他所有插件一样,都只作用于本模块,只是我们通过配置使得该插件与其他模块发生耦合,下面配置的意思是将本模块在dependencies
下声明的除groupId
为com.sigalhu.mmp
的所有依赖拷贝到打包路径下的lib
文件夹中。
<project>
...
<dependencies>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-dalartifactId>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-integrationartifactId>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-commonsartifactId>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-bizartifactId>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-serviceartifactId>
dependency>
<dependency>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-apiartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-dependency-pluginartifactId>
<version>2.8version>
<executions>
<execution>
<id>copy-libsid>
<phase>process-resourcesphase>
<goals>
<goal>copy-dependenciesgoal>
goals>
<configuration>
<excludeGroupIds>com.sigalhu.mmpexcludeGroupIds>
<includeScope>compileincludeScope>
<outputDirectory>${project.build.directory}/liboutputDirectory>
configuration>
execution>
executions>
plugin>
plugins>
build>
project>
我们通过配置maven-dependency-plugin
将各个子模块的jar
包拷贝到打包路径下的core
文件夹下,我们在artifactItems
下声明想要拷贝的模块,由于我们在multi-module-project
的POM
中将mmp-assembly
模块放在modules
的最后一个,因此当对mmp-assembly
进行打包时,其他子模块必定已经打包完毕,即jar
包必定存在。
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-dependency-pluginartifactId>
<version>2.8version>
<executions>
...
<execution>
<id>copy-coreid>
<phase>packagephase>
<goals>
<goal>copygoal>
goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-dalartifactId>
artifactItem>
<artifactItem>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-integrationartifactId>
artifactItem>
<artifactItem>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-commonsartifactId>
artifactItem>
<artifactItem>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-bizartifactId>
artifactItem>
<artifactItem>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-serviceartifactId>
artifactItem>
<artifactItem>
<groupId>com.sigalhu.mmpgroupId>
<artifactId>mmp-apiartifactId>
artifactItem>
artifactItems>
<outputDirectory>${project.build.directory}/coreoutputDirectory>
configuration>
execution>
executions>
plugin>
plugins>
build>
project>
在实际开发中,我们一般都有不同的环境,例如测试环境、开发环境、稳定环境、预发环境、线上环境等,不同环境下,配置文件中的配置各不相同,例如数据库的配置,各个环境下所存取的数据库肯定不会是同一个。
在multi-module-project
下新建settings
文件夹,并在该文件夹下新建不同环境的配置文件。
在各配置文件中,我们声明了一个属性用来表示不同的环境。
# mmp-test.properties
user.env=_test
# mmp-dev.properties
user.env=_dev
# mmp-stable.properties
user.env=_stable
# mmp-preonline.properties
user.env=_preonline
# mmp-online.properties
user.env=_online
同时,我们将mmp-assembly
模块的目录结构修改如下:
其中bin
文件夹中是我们项目的启动脚本,resources
文件夹中是我们项目的配置文件,可以看到该属性值是未定的,接下来我们将利用Maven
的profile
与filters
来将下面配置文件的${…}
替换为settings
文件夹中配置文件的对应属性值。
# settings.properties
user.env=${user.env}
在下面的配置中,我们将id
为stable
的profile
设置为默认激活,当打包该项目时,如果我们没有指定profile
,则filter
下的${profile.name}
的将会被替换为stable
,此时mmp-assembly
模块的settings.properties
中的${…}
会被替换为mmp-stable.properties
中属性的值。
<project>
...
<profiles>
<profile>
<id>testid>
<activation>
<activeByDefault>falseactiveByDefault>
activation>
<properties>
<profile.name>testprofile.name>
properties>
profile>
<profile>
<id>devid>
<activation>
<activeByDefault>falseactiveByDefault>
activation>
<properties>
<profile.name>devprofile.name>
properties>
profile>
<profile>
<id>stableid>
<activation>
<activeByDefault>trueactiveByDefault>
activation>
<properties>
<profile.name>stableprofile.name>
properties>
profile>
<profile>
<id>preonlineid>
<activation>
<activeByDefault>falseactiveByDefault>
activation>
<properties>
<profile.name>preonlineprofile.name>
properties>
profile>
<profile>
<id>onlineid>
<activation>
<activeByDefault>falseactiveByDefault>
activation>
<properties>
<profile.name>onlineprofile.name>
properties>
profile>
profiles>
<build>
<filters>
<filter>../settings/mmp-${profile.name}.propertiesfilter>
filters>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<filtering>truefiltering>
<includes>
<include>*.propertiesinclude>
includes>
resource>
resources>
...
build>
project>
现在如果我们对项目执行package
命令,可以看到如下图所示,配置文件、子模块还有依赖都位于各自文件夹下,这里为了便于理解,我们注释了junit
的依赖范围,因此junit
及其依赖会被拷贝到lib
文件夹下。
下面我们使用maven-assembly-plugin
将以上这些包和文件再加上启动脚本打包成zip
压缩文件。
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-assembly-pluginartifactId>
<version>2.5.3version>
<configuration>
<finalName>${project.artifactId}-${project.version}finalName>
<descriptors>
<descriptor>src/main/assembly/assembly.xmldescriptor>
descriptors>
<formats>
<format>zipformat>
formats>
<appendAssemblyId>falseappendAssemblyId>
<outputDirectory>targetoutputDirectory>
<attach>falseattach>
configuration>
<executions>
<execution>
<phase>packagephase>
<goals>
<goal>singlegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
project>
descriptors
中指定的assembly.xml
文件配置如下:
<assembly>
<id>assemblyid>
<includeBaseDirectory>falseincludeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}/classesdirectory>
<outputDirectory>confoutputDirectory>
fileSet>
<fileSet>
<directory>src/main/assembly/bindirectory>
<outputDirectory>binoutputDirectory>
fileSet>
<fileSet>
<directory>${project.build.directory}/libdirectory>
<outputDirectory>liboutputDirectory>
fileSet>
<fileSet>
<directory>${project.build.directory}/coredirectory>
<outputDirectory>coreoutputDirectory>
fileSet>
fileSets>
assembly>
在idea
中,我们可以在Profiles
中勾选不同profile
来针对不同环境进行打包,如果Profiles
中没有我们定义的profile
,可以点击下图左上角的Reimport All Maven Projects
重新载入。
在构建项目时,我们先执行clean
命令清除打包路径下的文件,然后执行package
命令进行打包。
如果我们想要在构建时不执行测试代码,可以选中上图菜单栏的倒数第二个按钮来跳过测试,但需要注意的是,这种方法只会不执行测试代码,测试代码还是会被编译,我们可以通过自定义命令来跳过测试代码的编译与执行。
项目源码:https://github.com/SigalHu/multi-module-project
学习更多:https://github.com/SigalHu/java-service-exercises