概述

在实际项目开发中,我们通常需要针对不同的环境(开发、测试、生产)使用不同的配置文件。Maven 提供了 Profile 机制,可以在打包时根据指定的环境参数,将对应的配置文件打包到 jar 包中。

  • 开发环境打包:jar 包中只包含 application.ymlapplication-dev.yml
  • 生产环境打包:jar 包中只包含 application.ymlapplication-prod.yml
  • 避免将敏感的生产环境配置打包到开发环境 jar 中

配置步骤

1. 配置根 pom.xml

在项目根目录的 pom.xml 中添加 profiles 配置(如果已有则跳过):

<profiles>
    <!-- 开发环境 -->
    <profile>
        <id>dev</id>
        <properties>
            <profileActive>dev</profileActive>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>

    <!-- 生产环境 -->
    <profile>
        <id>prod</id>
        <properties>
            <profileActive>prod</profileActive>
        </properties>
    </profile>
</profiles>

<build>
    <!-- 此处的{profileActive}参数名称就是上面profiles配置的参数名称 -->
    <finalName>{project.artifactId}-{profileActive}</finalName>

    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>application.yml</include>
                <include>application-{profileActive}.yml</include>
                <include>mybatis/**.xml</include>
                <include>mapper/**/*.xml</include>
                <include>static/**</include>
                <include>templates/**</include>
                <include>banner.txt</include>
                <include>*.xml</include>
                <include>*.properties</include>
                <include>i18n/*.properties</include>
            </includes>
        </resource>
    </resources>

    <plugins>
        <!-- 其他插件配置 -->
    </plugins>
</build>

说明:

  • <id> 定义 profile 的名称,打包时通过 -P 参数指定
  • <properties> 中定义的变量可以在其他配置文件中通过 @变量名@ 引用
  • <activeByDefault>true</activeByDefault> 设置默认激活的环境
  • <filtering>true</filtering>:启用资源过滤,Maven 会替换文件中的占位符
  • <includes>:指定需要打包的文件,只有列出的文件会被打包到 jar 中
  • application-${profileActive}.yml:动态引用当前激活的环境配置文件

2. 配置 application.yml

在主配置文件 application.yml 中使用占位符:

spring:
  profiles:
    active: @profileActive@

说明:

  • @profileActive@ 会在打包时被替换为实际的环境值(dev 或 prod)
  • 打包后,dev 环境会变成 active: dev,prod 环境会变成 active: prod

3. 创建环境配置文件

创建不同环境的配置文件:

  • application-dev.yml:开发环境配置
  • application-prod.yml:生产环境配置

在这些文件中配置环境特定的参数,如数据库连接、Redis 地址等。

使用方法

打包命令

# 打包开发环境(使用默认环境)
mvn clean package

# 明确指定开发环境
mvn clean package -P dev

# 打包生产环境
mvn clean package -P prod

# 跳过测试打包
mvn clean package -P prod -Dmaven.test.skip=true

验证打包结果

打包完成后,可以解压 jar 包查看:

# 解压 jar 包
jar -xf target/nrms-admin-prod.jar

# 查看配置文件
cat BOOT-INF/classes/application.yml
ls BOOT-INF/classes/application-*.yml

2. 资源过滤的影响

启用 <filtering>true</filtering> 后,Maven 会扫描并替换所有文件中的占位符,这可能导致:

  • 二进制文件损坏:图片、字体等二进制文件可能被破坏
  • 性能影响:大量文件需要扫描处理

解决方案:

<resources>
    <!-- 需要过滤的文本文件 -->
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
            <include>**/*.yml</include>
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
    </resource>
    <!-- 不需要过滤的二进制文件 -->
    <resource>
        <directory>src/main/resources</directory>
        <filtering>false</filtering>
        <excludes>
            <exclude>**/*.yml</exclude>
            <exclude>**/*.properties</exclude>
            <exclude>**/*.xml</exclude>
        </excludes>
    </resource>
</resources>

3. 常见问题

问题 1:打包后占位符没有被替换

原因:

  • 没有启用 <filtering>true</filtering>
  • 占位符语法错误(使用了 ${}而不是 @@

解决:

  • 检查 pom.xml 中的 <filtering> 配置
  • 确认使用正确的占位符语法 @变量名@

问题 2:打包后缺少某些文件

原因:

  • 使用了 <includes> 但没有列出所有需要的文件

解决:

  • 检查 resources 目录,确保所有文件都在 <includes>
  • 或者改用 <excludes> 方案

问题 3:jar 包名称不包含环境标识

原因:

  • <finalName> 没有使用环境变量

解决:

<finalName>{project.artifactId}-{profileActive}</finalName>

4. 最佳实践

  1. 环境配置分离:将环境特定的配置放在 application-{env}.yml 中,通用配置放在 application.yml

  2. 敏感信息处理

    • 生产环境的敏感信息(数据库密码、API 密钥)不要提交到代码仓库
    • 使用配置中心(如 Nacos、Apollo)或环境变量管理敏感信息
  3. 默认环境设置
    • 设置 dev 为默认环境,方便本地开发
    • 生产环境必须明确指定 -P prod
  4. 文件命名规范
    • jar 包名称包含环境标识:${project.artifactId}-${profileActive}
    • 便于区分不同环境的部署包

验证配置

1. 检查占位符替换

打包后查看 jar 包中的 application.yml,应该看到:

active: prod  # 而不是 @profileActive@

2. 检查配置文件

应该只看到:

BOOT-INF/classes/application.yml
BOOT-INF/classes/application-prod.yml

不应该包含 application-dev.yml

扩展阅读

总结

Maven 多环境打包通过 Profile 机制和资源过滤实现:

  1. 定义 Profile:在 pom.xml 中定义不同环境的 profile
  2. 配置资源过滤:启用 filtering 并指定需要打包的文件
  3. 使用占位符:在配置文件中使用 @变量名@ 占位符
  4. 打包时指定环境:使用 mvn clean package -P 环境名 打包

这种方式可以确保每个环境的 jar 包只包含对应环境的配置,提高了安全性和部署的可靠性。