1.Spring Profile
Spring可使用Profile决定程序在不同环境下执行情况,包含配置、加载Bean、依赖等。
Spring的Profile一般项目包含:dev(开发), test(单元测试), qa(集成测试), prod(生产环境)。由spring.profiles.active属性决定启用的profile。
SpringBoot的配置文件默认为 application.properties(或yaml,此外仅以properties配置为说明)。不同Profile下的配置文件由application-{profile}.properties管理,同时独立的 Profile配置文件会覆盖默认文件下的属性。
2.Maven Profile
Maven同样也有Profile设置,可在构建过程中针对不同的Profile环境执行不同的操作,包含配置、依赖、行为等。
Maven的Profile由 pom.xml 的标签管理。每个Profile中可设置:id(唯一标识), properties(配置属性), activation(自动触发的逻辑条件), dependencies(依赖)等。
每个项目都会有多套运行环境(开发,测试,正式等等),不同的环境配置也不尽相同(如jdbc.url),借助Jenkins和自动部署提供的便利,我们可以把不同环境的配置文件单独抽离出来,打完包后用对应环境的配置文件替换打包后的文件,其实maven已经给我们提供了替换方案:profile + filtering
Filtering
Filtering 是 maven 的 resource 插件 提供的功能,作用是用环境变量、pom文件里定义的属性和指定配置文件里的属性替换属性(*.properties)文件里的占位符(${jdbc.url}),具体使用如下:
在src/main/resources目录有个配置文件jdbc.properties,内容如下:
jdbc.url=${pom.jdbc.url}
jdbc.username=${pom.jdbc.username}
jdbc.passworkd=${pom.jdbc.password}
配置 resource 插件,启用filtering功能并添加属性到pom:
<project>
...
<!-- 用pom里定义的属性做替换 -->
<properties>
<pom.jdbc.url>jdbc:mysql://127.0.0.1:3306/dev</pom.jdbc.url>
<pom.jdbc.username>root</pom.jdbc.username>
<pom.jdbc.password>123456</pom.jdbc.password>
</properties>
<build>
...
<!-- 可以把属性写到文件里,用属性文件里定义的属性做替换 -->
<filters>
<filter>src/main/filters.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
...
</project>
编译包后target目录下的jdbc.properties:
jdbc.url=jdbc:mysql://127.0.0.1:3306/dev
jdbc.username=root
jdbc.passworkd=123456
Profile 简介
什么是profile?就像一样是pom文件里的一个xml元素,在profile里几乎可以定义所有在pom里的定义的内容(,,插件配置等等,不过不能再定义他自己了)。当一个profile被激活时,它定义的,等就会覆盖掉原pom里定义的相同内容,从而可以通过激活不同的profile来使用不同的配置。
<!-- profile 的感性认识 -->
<project>
...
<profiles>
<profile>
<id>dev</id>
<properties>
<active.profile>dev</active.profile>
<pom.jdbc.url>jdbc:mysql://127.0.0.1:3306/dev</pom.jdbc.url>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependencies>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
...
</project>
Profile 如何配置
可以在两个位置配置profile:settings.xml 和 pom.xml
settings.xml里定义的profile是全局的,对所有的项目都可用,在里面定义的配置项也稍微少了些,只能定义远程服务器的信息和属性信息(,, )。这些信息在pom.xml里也是可以定义的。
pom.xml里可以定义的配置如下:
<repositories>
<pluginRepositories>
<dependencies>
<plugins>
<properties>
<modules>
<reporting>
<dependencyManagement>
<distributionManagement>
以及build下的:
<defaultGoal>
<resources>
<testResources>
<finalName>
如果profile被激活,profile里的配置和原pom的配置会做覆盖合并。
如何激活Profile
可以通过多种方式激活profile(显式的,隐式的)
显式的激活
通过maven 的-P参数激活指定的profile,参数的值是profile的id,多个profile以逗号分割,如果不想激活某个默认的profile,就在它的id前加个!
mvn -U clean package -Ptest,local,!ignore
IDEA里则可以在 Maven Projects 里直接勾选想要激活的profile
隐式的激活
配置profile时,可以在 的 元素下配置隐式激活的信息。
默认激活
pom.xml文件里
<!-- 默认激活 -->
<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
settings.xml文件里则是通过来配置默认激活的profile列表
<activeProfiles>
<activeProfile>artifactory</activeProfile>
</activeProfiles>
根据操作系统类型激活
<profiles>
<profile>
<activation>
<os>
<!-- 不必指定所有信息 -->
<name>linux</name>
<family>unix</family>
<arch>amd64</arch>
<version>3.19.0-30-generic</version>
</os>
</activation>
</profile>
</profiles>
根据JDK版本激活
<!-- 如果jdk的版本为1.8则激活该profile -->
<profiles>
<profile>
<activation>
<jdk>1.8</jdk>
</activation>
</profile>
</profiles>
等等很多方法。
3.Maven 管理 Spring Profile
由于构建是基于Maven(或Gradle,此处仅以Maven说明)。所以使用Maven管理Spring构建时的Profile是非常方便的。
Maven管理Spring Profile分五步,以下详细介绍。
3.1 去掉默认的 Tomcat依赖
在SpringBoot MVC项目中,默认以内嵌Tomcat运行,如果需要特殊的设置或者使用Undertow,需要去掉默认的Tomcat依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
如果你同时使用了 MyBatis,需要去掉tomcat-jdbc依赖:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
3.2 Maven Profile设置
在项目(如果有模块为具体模块)的pom.xml下设置:
<!-- Maven控制Spring Profile -->
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profileActive>dev</profileActive>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>prod</id>
<properties>
<profileActive>prod</profileActive>
</properties>
</profile>
</profiles>
从上面的配置可以看出,Maven的Profile配置了两个:dev和prod,并且在dev中使用了内嵌Tomcat,而 prod 中没有,所以这两个Profile打包的文件dev可以直接运行(Plugin使用了SpringBoot Plugin),而prod并不能直接运行(或部署在外部Tomcat下,并不推荐这样,后面会说明)。
properties中的profileActive是我们申明的属性,此处对应Spring的Profile值。
3.3 Maven资源过滤
SpringBoot的 Profile选择需要在 application.properties中配置,如果定死在文件,那么每次打包都需要手动修改,很麻烦,而且容易出错。
Maven的资源过滤功能可以实现在构建时修改以“@xxx@”表示的属性。资源过滤需要在pom.xml的标签下配置 resources:
<!-- profile对资源的操作 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>application*.properties</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<!-- 是否替换@xx@表示的maven properties属性值 -->
<filtering>true</filtering>
<includes>
<include>application.properties</include>
<include>application-${profileActive}.properties</include>
</includes>
</resource>
</resources>
上面的第一个resource去掉了src/main/resources下的所有application*.properties文件,“*”是通配符,表示此处有任何内容(没有也可以)都匹配。
第二个resource添加了application.properties默认配置文件和由profileActive属性决定的相应profile配置文件。并且filtering为true表示,会将文件内容的“@xx@”替换为相应的变量(如文件中的@profileActive@会替换为profileActive属性值)。
3.4 Spring配置Profile
在application.properties默认配置文件中配置:
spring.profiles.active=@profileActive@
@profileActive@表示该属性值会在maven构建时被替换掉。
3.5 构建
构建命令:
mvn clean package -Pdev
上面的命令会根据Maven Profile的 dev构建环境包,如果需要prod包,则把-P的参数替换成prod即可。
常用maven命令如下回顾:
mvn -v
显示maven安装版本信息
mvn clean
清理项目打包文件,即项目下的target目录
mvn compile
编译项目下的src/main/Java目录源代码
mvn package
项目打包,在项目target目录下生成编译后的jar或war等文件
mvn install
项目打包并发布到本地仓库
mvn deploy
项目打包并发布到远程仓库
mvn test
单元测试命令,执行src/test/java/下的junit的单元测试用例
mvn site
生成项目相关信息的网站
mvn eclipse:eclipse
将项目转化eclipse项目
mvn dependency:tree
打印出项目的整个依赖关系树
mvn archetype:generate
创建一个maven普通java项目
mvn tomcat:run
在tomcat容器中运行web应用,需要在pom文件中配置tomcat插件
mvn jetty:run
在jetty容器中运行web应用,需要在pom文件中配置jetty插件
命令参数
-D 传入属性参数
-P 使用指定的profile配置
-e 显示maven运行时的报错信息
-o 离线本地式执行命令,不去远程仓库更新包
-X 显示maven允许的debug信息
-U 强制远程更新,否则默认每天只更新一次
比如-D的使用:mvn package -Dmaven.test.skip=true,即打包的时候跳过单元测试,install、deplay命令都可以使用。
可以输入mvn -h获取更多命令的帮助。
为了方便我会在每个项目下生成一个build.sh文件,内容如下:
#!/bin/bash
profileActive=prod
if [ -n "$1" ]; then
profileActive=$1
fi
mvn clean package -Dmaven.test.skip=true -P$profileActive
该脚本接收一个参数,即打包对应的Profile。默认情况下如果不带参数,会打包prod环境包。
需要注意的是,该命令跳过了测试。
4. 总结
完成了上面的五步,即可使项目根据你的构建参数的不同,打包出不同环境下运行的包。
第1步去掉了SpringBoot内嵌的tomcat和tomcat-jdbc。使得我们可以决定在什么情况下使用何种容器运行我们的项目。
第2步配置了Maven构建Porfile,使得构建可根据我们的指令分发不同的包。
第3步配置了Maven资源过滤,不仅使得不同Profile下的资源文件互不可见,且替换了资源文件中以“@xx@”表示的属性值。
第4步使Spring的Profile由Maven决策,这样,我们就不用每次打包都修改Spring的Profile配置了。
第5步展示了如何执行不同Profile下的构建命令,并且使用了一个Shell脚本方便我们执行构建和跳过测试(多数时候我们在构建项目时先测试,并不需要在构建时测试,测试和构建的解耦使得我们更专注。但同时,如果你忘记了前置测试,也可能会引发未察觉的测试问题)。