注意:SpringBoot框架,默认已集成了插件:maven-compiler-plugin + maven-resources-plugin
maven-resources-plugin 是 Maven 自带的核心插件,专门负责处理项目中的资源文件(非代码文件,比如配置文件、静态文件、模板等)。
核心作用(一句话)
把你项目里的资源文件(src/main/resources 下的文件)自动复制到编译后的目录(target/classes),还能替换配置文件里的变量(比如把 ${jdbc.url} 替换成真实数据库地址)。
一、最基础默认功能:复制资源文件
Maven 默认就会用这个插件,不用手动配置,它会自动:
- 读取
src/main/resources下的所有文件 - 复制到
target/classes目录(打包后就是 jar/war 里的根目录)
示例
项目结构:
src/
main/
resources/
application.yml # 配置文件
static/ # 静态文件
执行 mvn compile 后:
target/
classes/
application.yml
static/
插件自动把资源复制到了编译目录,程序运行时才能读到这些配置。
二、最常用功能:过滤变量(替换配置文件中的占位符)
这是这个插件最实用的功能:在配置文件里写 ${变量名},插件自动把它替换成真实值。
1. 配置文件(带变量)
src/main/resources/application.yml
app:
name: ${project.artifactId}
version: ${project.version}
env: ${env.name}
2. pom.xml 定义变量(资源变量替换,也叫 filtering)
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo-app</artifactId>
<version>1.0.0</version>
<properties>
<env.name>dev</env.name>
</properties>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>*.properties</include>
</includes>
</resource>
</resources>
</build>
</project>
执行:
mvn process-resources
生成的 target/classes/application.properties 会变成:
app: name: demo-app version: 1.0.0 env: dev
也可以用命令行覆盖:
mvn process-resources -Denv.name=prod
生成结果:
app: name: demo-app version: 1.0.0 env: prod
不过在 Spring Boot 项目里要特别注意:application.yml 里经常也会写 Spring 自己的占位符,比如:
server:
port: ${SERVER_PORT:8080}
这个 ${SERVER_PORT:8080} 是希望 Spring Boot 在运行时解析的,不一定希望 Maven 在构建时替换。为了避免 Maven filtering 和 Spring Boot 占位符冲突,常见做法是改用 @...@ 作为 Maven 替换符。
例如:
app:
name: @project.artifactId@
version: @project.version@
env: @env.name@
server:
port: ${SERVER_PORT:8080}
然后在 pom.xml 里配置 Maven 使用 @ 作为 delimiter:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>application.yml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
</build>
这样 Maven 只替换:
@project.artifactId@ @project.version@ @env.name@
而不会动 Spring Boot 运行时需要解析的:
${SERVER_PORT:8080}
所以在 Spring Boot 项目里,更推荐这种写法:
app: name: @project.artifactId@ version: @project.version@ env: @env.name@
三、进阶用法
1. 指定多个资源目录、排除 / 包含文件
你可以自定义:哪些文件要复制、哪些不要、从哪里复制。
示例:只复制 .yml 配置,排除 .txt 文件
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<!-- 包含:只处理 yml 文件 -->
<includes>
<include>**/*.yml</include>
</includes>
<!-- 排除:不处理 txt 文件 -->
<excludes>
<exclude>**/*.txt</exclude>
</excludes>
</resource>
</resources>
</build>
2. 复制额外资源目录
除了标准的资源处理,copy-resources 目标非常有用,常用于多模块项目中共享文件。
示例:将前端资源复制到Web应用目录
在一些项目中,你可能需要将 src/main/webapp 之外的资源复制到打包目录。下面的配置会在 validate 阶段(较早的生命周期阶段),将 common-assets 模块中的文件复制到当前项目的 Web 应用目录中,以供 war 插件打包。
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>copy-js-to-webapp</id> <!-- 唯一标识 -->
<phase>validate</phase> <!-- 绑定到validate阶段 -->
<goals>
<goal>copy-resources</goal> <!-- 使用copy-resources目标 -->
</goals>
<configuration>
<!-- 目标目录:Web应用下的assets目录 -->
<outputDirectory>${project.basedir}/src/main/webapp/assets</outputDirectory>
<!-- 要复制的资源 -->
<resources>
<resource>
<!-- 源目录:来自其他模块或当前模块的某个路径 -->
<directory>${project.parent.basedir}/common-assets/target/js</directory>
<!-- 只复制所有js文件 -->
<includes>
<include>*.js</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
另外一个示例:
有时候资源文件不在默认的 src/main/resources 里,比如:
src/non-packaged-resources/banner.txt
可以用 copy-resources 手动复制:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>copy-extra-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/extra-resources</outputDirectory>
<resources>
<resource>
<directory>src/non-packaged-resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
这样在 validate 阶段,会把 src/non-packaged-resources 下的资源复制到:
target/extra-resources
官方文档也给出了类似用法:copy-resources 可以复制不在默认 Maven 布局中、或者没有在 build/resources 中声明的资源,并绑定到某个生命周期阶段。
四、常见用途总结
maven-resources-plugin 常用于:
- 把配置文件复制到 classpath
例如application.properties、logback.xml、MyBatis mapper XML。 - 不同环境替换不同配置
例如开发环境输出env=dev,生产环境输出env=prod。 - 构建时注入版本号
例如把${project.version}写入配置文件,程序运行时可以显示当前版本。 - 包含或排除某些资源文件
例如只处理.properties,不处理图片、证书、二进制文件。
需要注意:不要随便对图片、PDF 等二进制文件开启 filtering,因为变量替换过程可能导致二进制文件损坏;官方文档也建议把需要过滤的文本资源和不需要过滤的二进制资源分开处理。
简单理解就是:maven-compiler-plugin 负责 编译 Java 代码,而 maven-resources-plugin 负责 搬运和加工资源文件。