springBoot中的 pom.xml文件 bulid学习
最近在学习springBoot中,看到了 pom.xml中的bulid代码:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
这段 Maven pom.xml 配置片段主要包含两个核心部分:Spring Boot 打包插件和资源过滤配置。以下是对其作用的详细解析及潜在风险提示。
1. spring-boot-maven-plugin插件
该插件是 Spring Boot 官方提供的核心构建插件,其主要作用是将普通的 Maven JAR 包转换为可独立运行的“Fat Jar”(或称 Uber Jar)。
- 打包可执行 Jar:它会将项目的所有依赖库(dependencies)重新打包并嵌入到最终的 JAR 文件中,同时生成特定的目录结构(如
BOOT-INF/lib、BOOT-INF/classes)和启动类信息(Start-Class)。这使得生成的 JAR 包可以通过java -jar app.jar命令直接运行,无需额外配置 Classpath。 - 开发支持:在开发阶段,该插件还支持热部署(DevTools)和应用的快速重启,提升开发效率。
- 构建信息生成:它可以生成
build-info.properties文件,包含构建时间、版本等信息,便于应用监控和排查问题。
注意:如果未指定 <version>,Maven 通常会继承 spring-boot-starter-parent 中定义的版本。若未使用 parent POM,则必须显式指定版本,否则可能导致构建失败或行为不可控。
2. <resources> 与 <filtering>true</filtering>
这部分配置启用了 Maven 的资源过滤(Resource Filtering)功能。
- 占位符替换:当
<filtering>设置为true时,Maven 在将src/main/resources目录下的文件复制到输出目录(如target/classes)之前,会扫描文件内容。它会识别其中的${...}占位符(例如${project.version}、${db.url}),并将其替换为pom.xml中定义的属性值、系统属性或 profile 中激活的属性值。 - 多环境适配:这是实现多环境配置(开发、测试、生产)的关键机制。结合
<profiles>,可以为不同环境定义不同的属性值,从而在构建时自动生成对应环境的配置文件。 - 资源过滤开启后,资源文件中包含
${...}的地方会被替换成 POM 文件中的属性或系统属性。因此如果你有配置文件比如application.properties,文件内的变量可以被替换。 - 但要注意,部分二进制文件(如图片、jar 包等)不应该开启过滤,否则会导致文件损坏。
- 通常只对文本资源开启过滤,或将需要过滤的资源独立目录单独设置资源过滤
⚠️ 重要风险与最佳实践
虽然上述配置很常见,但全局开启资源过滤(<filtering>true</filtering>)存在严重风险,特别是当资源目录中包含二进制文件时。
风险:二进制文件损坏
Maven 的资源过滤机制是基于文本处理的。如果 src/main/resources 目录下包含二进制文件(如 .keystore、.jks、.p12、.png、.jpg、.gif、.woff 等),开启过滤后,Maven 会尝试以文本方式读取并替换这些文件中的内容。这会导致二进制数据被破坏,从而使证书失效、图片无法显示或字体加载错误。
推荐的最佳实践配置
为了安全地使用资源过滤,建议采用排除二进制文件或分离配置的策略。以下是更 robust 的配置示例:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<!-- 配置1:处理需要过滤的文本文件 -->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<!-- 排除所有已知的二进制文件后缀 -->
<excludes>
<exclude>**/*.keystore</exclude>
<exclude>**/*.jks</exclude>
<exclude>**/*.p12</exclude>
<exclude>**/*.pfx</exclude>
<exclude>**/*.cer</exclude>
<exclude>**/*.png</exclude>
<exclude>**/*.jpg</exclude>
<exclude>**/*.jpeg</exclude>
<exclude>**/*.gif</exclude>
<exclude>**/*.ico</exclude>
<exclude>**/*.woff</exclude>
<exclude>**/*.woff2</exclude>
<exclude>**/*.ttf</exclude>
<exclude>**/*.eot</exclude>
<exclude>**/*.svg</exclude> <!-- svg虽是文本,但通常不建议过滤以防万一 -->
</excludes>
</resource>
<!-- 配置2:处理不需要过滤的二进制文件 -->
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.keystore</include>
<include>**/*.jks</include>
<include>**/*.p12</include>
<include>**/*.png</include>
<include>**/*.jpg</include>
<!-- 包含其他所有二进制格式 -->
</includes>
</resource>
</resources>
</build>
或者,使用 maven-resources-plugin 的 <nonFilteredFileExtensions> 配置(需确保插件版本较新,如 3.3.1+):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>keystore</nonFilteredFileExtension>
<nonFilteredFileExtension>jks</nonFilteredFileExtension>
<nonFilteredFileExtension>p12</nonFilteredFileExtension>
<nonFilteredFileExtension>png</nonFilteredFileExtension>
<nonFilteredFileExtension>jpg</nonFilteredFileExtension>
<nonFilteredFileExtension>gif</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
总结
你提供的配置实现了 Spring Boot 的可执行打包和动态资源替换功能,但在实际项目中,务必注意避免对二进制资源文件进行过滤,否则会导致应用运行时出现难以排查的错误。建议采用排除法或专门的非过滤配置来保护二进制文件。
注意一个templates目录下的
- Thymeleaf 模板(
.html) - FreeMarker 模板(
.ftl) - Velocity 模板(
.vm)
1、这些模板文件会在运行时由对应的模板引擎加载并渲染。
2、是否开启过滤的考虑点
开启过滤:
- 资源过滤会在构建时将文件中的
${...}或其他占位符替换成 Maven 属性或自定义属性的值。 - 如果你希望在构建时就动态替换模板中的某些变量(如版本号、构建时间、服务器地址等),可以开启过滤。
- 但要特别注意,模板引擎本身常用
${...}来表示变量,如果 Maven 过滤抢先把它替换了,模板的动态功能就会失效。
关闭过滤:
- 如果模板中的
${...}是模板引擎要在运行时解析的变量,最好不要开启过滤。 - 避免构建时把模板里的变量“提前替换”,破坏了模板的动态渲染功能。
- 一般建议把模板文件保持原样,交给模板引擎处理。
3. 典型建议
- 不要对存放模板的
templates目录开启<filtering>true</filtering>。 - 如果确实需要过滤某些配置文件或资源,可以专门建立一个带过滤的资源目录(比如
src/main/filtered-resources),单独管理。 - 如果想在模板里引用类似构建时间、版本号这种固定数据,可以通过模板引擎传递参数或使用占位符文件替换机制,而不是 Maven 过滤。
4. 具体示例
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering> <!-- 关闭过滤 -->
</resource>
</resources>
模板目录(如 templates)一般在 src/main/resources/templates 下,默认继承了上述配置。
总结
| 是否应该过滤模板资源 | 理由 |
|---|---|
| 否 | 保持模板中 ${} 由模板引擎渲染,不被 Maven 替换 |
| 是(少见) | 构建时需要替换特定 Maven 属性,且模板不影响动态变量解析 |
浙公网安备 33010602011771号