整个maven系列的内容前后是有依赖的,如果之前没有接触过maven,建议从第一篇看起,本文尾部有maven完整系列的连接。
如果你作为公司核心开发,打算使用maven来搭建项目骨架,这篇文章的内容是你必须要掌握的。
平时我们在开发系统的时候,会有开发环境、测试环境、线上环境,每个环境中配置文件可能都是不一样的,比如:数据库的配置,静态资源的配置等等,所以我们希望构建工具能够适应不同环境的构建工作,能够灵活处理,并且操作足够简单。Maven作为一款优秀的构建工具,这方面做的足够好了,能够很好的适应不同环境的构建工作,本文主要讲解maven如何灵活的处理各种不同环境的构建工作,废话不多说,上干货。
重点提示
本文中的所有案例均在上一篇的b2b
项目上进行操作,上一篇还没有看的可以移步过去看一下:Maven系列第8篇:大型Maven项目,快速按需任意构建,必备神技能!相知恨晚!
所有mvn命令均在b2b/pom.xml
所在目录执行。
Maven属性
自定义属性
maven属性前面我们有用到过,可以自定义一些属性进行重用,如下:
<properties>
<spring.verion>5.2.1.RELEASE</spring.verion>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.verion}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.verion}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.verion}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.verion}</version>
</dependency>
</dependencies>
可以看到上面依赖了4个spring相关的构建,他们的版本都是一样的,在properties
元素中自定义了一个spring.version
属性,值为spring的版本号,其他几个地方使用${}
直接进行引用,这种方式好处还是比较明显的,升级spring版本的时候非常方便,只需要修改一个地方,方便维护。
上面这个是maven自定义属性,需要先在properties
中定义,然后才可以在其他地方使用${属性元素名称}
进行引用。
maven的属性主要分为2大类,第一类就是上面说的自定义属性,另外一类是不需要自定义的,可以直接拿来使用的。
2类属性在pom.xml中都是采用${属性名称}
进行引用,maven运行的时候会将${}
替换为属性实际的值。
下面我们来看一下maven中不需要自定义的5类属性。
内置属性
${basedir}:表示项目根目录,即包含pom.xml文件的目录
${version}:表示项目的版本号
POM属性
用户可以使用该属性引用pom.xml文件中对应元素的值,例如${project.artifactId}就可以取到project->artifactId
元素的值,常用的有:
${pom.build.sourceDirectory}:项目的主源码目录,默认为src/main/java/
${project.build.testSourceDirectory}:项目的测试源码目录,默认为src/test/java/
${project.build.directory}:项目构建输出目录,默认为target/
${project.build.outputDirectory}:项目主代码编译输出目录,默认为target/classes
${project.build.testOutputDirectory}:项目测试代码编译输出目录,默认为target/test-classes
${project.groupId}:项目的groupId
${project.artifactId}:项目的artifactId
${project.version}:项目的version,与${version}等价
${project.build.finalName}:项目打包输出文件的名称,默认为${project.artifactId}-${project.version}
Settings属性
这种属性以settings.开头来引用~/.m2/settings.xml
中的内容,如:
${settings.localRepository}
指向用户本地仓库的地址。
java系统属性
所有java系统属性都可以使用maven属性来进行引用,例如${user.home}
指向了当前用户目录。
java系统属性可以通过mvn help:system
命令看到。
环境变量属性
所有的环境变量都可以使用env.开头的方式来进行引用,如:
${env.JAVA_HOME}
可以获取环境变量JAVA_HOME
的值。
用户可以使用mvn help:system
命令查看所有环境变量的值。
上面的maven属性,我们在pom.xml
中通过${属性名称}
可以灵活的引用,对我们写pom.xml文件帮助还是比较大的。
实操案例
将下面配置放在b2b-account-service/pom.xml
中:
<properties>
<!-- 项目的主源码目录,默认为src/main/java/ -->
<a>${pom.build.sourceDirectory}</a>
<!-- 项目的测试源码目录,默认为src/test/java/ -->
<b>${project.build.testSourceDirectory}</b>
<!-- 项目构建输出目录,默认为target/ -->
<c>${project.build.directory}</c>
<!-- 项目主代码编译输出目录,默认为target/classes -->
<d>${project.build.outputDirectory}</d>
<!-- 项目测试代码编译输出目录,默认为target/test-classes -->
<e>${project.build.testOutputDirectory}</e>
<!-- 项目的groupId -->
<f>${project.groupId}</f>
<!-- 项目的artifactId -->
<g>${project.artifactId}</g>
<!-- 项目的version,与${version}等价-->
<h>${project.version}</h>
<!-- 项目打包输出文件的名称,默认为${project.artifactId}-${project.version} -->
<i>${project.build.finalName}</i>
<!-- setting属性 -->
<!-- 获取本地仓库地址-->
<a1>${settings.localRepository}</a1>
<!-- 系统属性 -->
<!-- 用户目录 -->
<a2>${user.home}</a2>
<!-- 环境变量属性,获取环境变量JAVA_HOME的值 -->
<a3>${env.JAVA_HOME}</a3>
</properties>
然后在b2b/pom.xml
所在目录执行下面命令:
D:\code\IdeaProjects\b2b>mvn help:effective-pom -pl :b2b-account-service > 1.xml
上面这个命令会将mvn ...
执行的结果输出到b2b/1.xml
目录,mvn
这段命令有看不懂的朋友,可以去看看前面的文章。
b2b目录中产生了一个1.xml,如下:
我们打开1.xml看一下,部分内容如下:
<properties>
<a>D:\code\IdeaProjects\b2b\b2b-account\b2b-account-service\src\main\java</a>
<a1>${settings.localRepository}</a1>
<a2>C:\Users\Think</a2>
<a3>D:\installsoft\Java\jdk1.8.0_121</a3>
<b>D:\code\IdeaProjects\b2b\b2b-account\b2b-account-service\src\test\java</b>
<b2>D:\code\IdeaProjects\b2b</b2>
<c>D:\code\IdeaProjects\b2b\b2b-account\b2b-account-service\target</c>
<d>D:\code\IdeaProjects\b2b\b2b-account\b2b-account-service\target\classes</d>
<e>D:\code\IdeaProjects\b2b\b2b-account\b2b-account-service\target\test-classes</e>
<f>com.javacode2018</f>
<g>b2b-account-service</g>
<h>1.0-SNAPSHOT</h>
<i>b2b-account-service-1.0-SNAPSHOT</i>
</properties>
大家去和上面的pom.xml中的对比一下,感受一下!
多套环境构建问题
b2b-account-service
会操作数据库,所以我们需要一个配置文件来放数据库的配置信息,配置文件一般都放在src/main/resources
中,在这个目录中新建一个jdbc.properties
文件,内容如下:
jdbc.url=jdbc:mysql://localhost:3306/javacode2018?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
现在系统需要打包,我们运行下面命令
mvn clean package -pl :b2b-account-service
问题来了:
上面jdbc的配置的是开发库的db信息,打包之后生成的jar中也是上面开发环境的配置,那么上测试环境是不是我们需要修改上面的配置,最终上线的时候,上面的配置是不是又得重新修改一次,相当痛苦的。
我们能不能写3套环境的jdbc配置,打包的时候去指定具体使用那套配置?
还是你们聪明,maven支持这么做,pom.xml的project
元素下面提供了一个profiles
元素可以用来对多套环境进行配置。
在讲profiles的使用之前,需要先了解资源文件打包的过程。
理解资源文件打包过程
我们将src/main/resouces/jdbc.properties
复制一份到src/test/resources
目录,2个文件如下:
我们先运行一下下面命令:
mvn clean package -pl :b2b-account-service
输出如下:
D:\code\IdeaProjects\b2b>mvn clean package -pl :b2b-account-service
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.javacode2018:b2b-account-service >----------------
[INFO] Building b2b-account-service 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ b2b-account-service ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ b2b-account-service ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ b2b-account-service ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ b2b-account-service ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ b2b-account-service ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ b2b-account-service ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ b2b-account-service ---
[INFO] Building jar: D:\code\IdeaProjects\b2b\b2b-account\b2b-account-service\target\b2b-account-service-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.572 s
[INFO] Finished at: 2019-11-21T17:13:20+08:00
[INFO] ------------------------------------------------------------------------
再去看一下项目的target目录,如下图:
下面我们来对这个过程做详细分析:
从输出中可以看到有下面几行:
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ b2b-account-service ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
从上面输出中可以看出,使用了插件maven-resources-plugin的resources目标
,将src/main/resouces
目录中的资源文件复制到了target/classess
目录,复制了一个文件,复制过程中使用是GBK
编码。
还有几行输出如下:
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ b2b-account-service ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
从上面输出中可以看出,使用了插件maven-resources-plugin的testResources目标
,将src/main/resouces
目录中的资源文件复制到了target/classess
目录,复制了一个文件,复制过程中使用是GBK
编码。
resources目录中的文件一般放的都是配置文件,配置文件一般最好我们都不会写死,所以此处有几个问题:
-
这个插件复制资源文件如何设置编码?
-
复制的过程中是否能够对资源文件进行替换,比如在资源文件中使用一些占位符,然后复制过程中对这些占位符进行替换。
maven-resources-plugin
这个插件还真好,他也想到了这个功能,帮我们提供了这样的功能,下面我们来看看。
设置资源文件复制过程采用的编码
这个之前有提到过,有好几种方式,具体可以去前面的文章看一下。这里只说一种:
<properties>
<encoding>UTF-8</encoding>
</properties>
设置资源文件内容动态替换
资源文件中可以通过${maven属性}
来引用maven属性中的值,打包的过程中这些会被替换掉,替换的过程默认是不开启的,需要手动开启配置。
修改src/main/resource/jdbc.properties
内容如下:
jdbc.url=${jdbc.url}
jdbc.username=${jdbc.username}
jdbc.password=${jdbc.password}
修改src/test/resource/jdbc.properties
内容如下:
jdbc.url=${jdbc.url}
jdbc.username=${jdbc.username}
jdbc.password=${jdbc.password}
b2b-account-service/pom.xml
中加入下面内容:
<properties>
<!-- 指定资源文件复制过程中采用的编码方式 -->
<encoding>UTF-8</encoding>
<jdbc.url>jdbc:mysql://localhost:3306/javacode2018?characterEncoding=UTF-8</jdbc.url>
<jdbc.username>root</jdbc.username>
<jdbc.password>root</jdbc.password>
</properties>
开启动态替换配置,需要在pom.xml中加入下面配置:
<build>
<resources>
<resource>
<!-- 指定资源文件的目录 -->
<directory>${project.basedir}/src/main/resources</directory>
<!-- 是否开启过滤替换配置,默认是不开启的 -->
<filtering>true</filtering>
</resource>
</resources>
<testResources>
<testResource>
<!-- 指定资源文件的目录 -->
<directory>${project.basedir}/src/test/resources</directory>
<!-- 是否开启过滤替换配置,默认是不开启的 -->
<filtering>true</filtering>
</testResource>
</testResources>
</build>
注意上面开启动态替换的元素是
filtering
。上面build元素中的
resources
和<