spring profile 与 maven profile 多环境管理

6,067 阅读5分钟

实际开发中一个项目至少对应开发、测试、生成三种环境,如何方便的管理多环境是今天的要讨论的主题

Spring Profile

Spring Profile 是 Spring 提供的多环境管理方案。

如图,每种环境都对应一个 properties 文件,然后在application.properties中配置一下要使用的环境

spring.profiles.active=dev

上面配置匹配的是 application-dev.properties,如果写的是test,则匹配 application-test.properties。也就是说,Spring Profile 对配置文件的命名有要求,必须是 application- 开头

除了配置环境外,一些不随环境而变化的配置也应该放到 application.properties中,application-.properties最好只存放与环境相关的配置项

以上就是 Spring Profile 给出的多环境管理方案。通过改变 spring.profiles.active的值来切换不同的环境。这种方法简单易懂,但有两个问题。

  1. 每次切换环境要手动修改 spring.profiles.active 的值
  2. 打包的时候,要手动删除其它环境的配置文件,不然其它环境的敏感信息就都打包进去了

为了解决这两个问题,我们需要 maven profile 的配合

maven profile

  maven 的 profile 可以让我们定义多套配置信息,并指定其激活条件,然后在不同的环境下使用不同的profile配置。   

profile 的定义位置

在maven中有两个地方可以配置 profile

  1. pom.xml中:这里面定义的 profile 作用范围是当前项目
  2. {user}/.m2/settings.xml中:这里面定义的 profile 作用范围是所有使用了该配置文件的项目

settings.xml中的 profile

不同的地方 profile 中能定义的信息也不相同

  • 由于settings.xml作用范围宽泛, profile 中只能定义一些公共信息,如下
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      https://maven.apache.org/xsd/settings-1.0.0.xsd">
    ...
    <profiles>
        <profile>
            <id>...</id>
            <activation>...</activation>
            <repositories>...</repositories>
        </profile>
    </profiles>
    ...
</settings>
  • id:该 profile 的唯一标识
  • activation:在哪些情况下激活 profile,这里面有多种策略可供选择,只要满足其中一个条件就激活
  • repositories:远程仓库

由于能配置的东西有限,一般都会将 maven profile 配置在pom.xml

pom.xml中 的profile

pom.xml中:profile 能定义的东西就非常多了,如下

<profiles>
    <profile>
        <id>..</id>
        <activation>...</activation>
        <build>...</build>
        <modules>...</modules>
        <repositories>...</repositories>
        <pluginRepositories>...</pluginRepositories>
        <dependencies>...</dependencies>
        <reporting>...</reporting>
        <dependencyManagement>...</dependencyManagement>
        <distributionManagement>...</distributionManagement>
    </profile>
</profiles>

当然我们的目的也不是把它配全,而是解决 Spring Profile 遗留下来的两个问题。

首先看第一个问题

问题1

"每次切换环境要手动修改spring.profiles.active的值"

这个问题就可以通过配置 profile 解决,在pom的根节点下添加

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <!-- activeByDefault 为 true 表示,默认激活 id为dev 的profile-->
            <activeByDefault>true</activeByDefault>
        </activation>
        <!-- properties 里面可以添加自定义节点,如下添加了一个env节点 -->
        <properties>
            <!-- 这个节点的值可以在maven的其他地方引用,可以简单理解为定义了一个叫env的变量 -->
            <env>dev</env>
        </properties>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <env>test</env>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <env>prod</env>
        </properties>
    </profile>
</profiles>

如上,定义了三套环境,其中id为dev的是默认环境,三套环境中定义了叫 env的“变量”

如果你用的是idea编辑器,添加好后,maven控件窗口应该会多出一个 Profiles,其中默认值就是上面配置的dev

最小化的 profiles 已经配置好了,通过勾选上图中的Profiles,就可以快速切换 maven的 profile 环境。

现在 maven profile 可以通过 勾选上图中的Profiles 快速切换环境

Spring Profile 还得通过 手动修改spring.profiles.active的值来切环境

现在的问题是怎样让 maven profile的环境与Spring Profile一一对应,达到切换maven profile环境时,Spring Profile环境也被切换了

还记得maven profile 中定义的 env "变量"吗,现在只需要把

spring.profiles.active=dev

改成

spring.profiles.active=@env@

就将maven profile 与 Spring Profile 环境关联起来了

当maven profile 将 环境切换成 test 时,在pom中定义的id为test的profile环境将被激活,在该环境下env的值是test,maven插件会将 @env@ 替换为 test,这样Spring Profile的环境也随之发生了改变。从上面可以看出,自定义的"变量"env的值还不能乱写,要与Spring Profile的环境相对应。

总结

  • 第一步,在pom文件中配置 profiles
  • 第二步,在application.properties配置文件中添加 spring.profiles.active=@env@

问题2

打包的时候,要手动删除其它环境的配置文件,不然其它环境的敏感信息就都打包进去了

解决这个问题需要在pom根节点下中配置 build 信息

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <excludes>
                <!--先排除application开头的配置文件-->
                <exclude>application*.yml</exclude>
            </excludes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <!--filtering 需要设置为 true,这样在include的时候,才会把
            配置文件中的@env@ 这个maven`变量`替换成当前环境的对应值  -->
            <filtering>true</filtering>
            <includes>
                <!--引入所需环境的配置文件-->
                <include>application.yml</include>
                <include>application-${env}.yml</include>
            </includes>
        </resource>
    </resources>
    <!--<plugins>-->
    <!--    <plugin>-->
    <!--        <groupId>org.springframework.boot</groupId>-->
    <!--        <artifactId>spring-boot-maven-plugin</artifactId>-->
    <!--    </plugin>-->
    <!--</plugins>-->
</build>
  • directory:资源文件所在目录
  • includes:需要包含的文件列表
  • excludes:需要排除的文件列表

如上,配置了两个 <resource>,第一个先排除了src/main/resources目录下所有 application 开头是配置文件,第二个在第一个的基础上添加了所需的配置文件。注意 application-${env}.yml,它是一个动态变化的值,随着当前环境的改变而改变,假如当前环境是 id叫 dev的 profile,那么env的值为 dev。

这样配置后,maven在build时,就会根据配置先排除掉指定的配置文件,然后根据当前环境添加所需要的配置文件。