导读:本期聚焦于落伍者创作的《Maven pom.xml资源过滤配置怎么用?resource filtering详解与避坑指南》,敬请观看详情。为什么同一个项目打出来的包,配置文件里的占位符有时能被替换,有时却原样输出了?问题的根源往往就在pom.xml的资源过滤配置上。本文系统讲解Maven中resource filtering的工作机制,包括resources节点、filtering开关、include与exclude的配合使用,以及通过properties自定义占位符变量传递到配置文件的具体做法。文中还分析了二进制文件被过滤后损坏、占位符未替换等典型问题的排查思路,并给出多环境profile结合资源过滤的实战配置示例,帮助开发者写出可维护、可移植的构建脚本。

Maven构建项目时,src/main/resources目录下的文件默认会被原样复制到classpath中,但实际开发中我们经常希望配置文件里的版本号、构建时间、数据库地址等信息在打包时自动替换。这个需求就要靠resource filtering来实现。不少人对这套配置一知半解,导致打包后配置文件出现占位符没被替换、图片被过滤器破坏等问题。本文从原理到实战,把pom.xml中资源过滤的配置方法讲透。

Maven pom.xml资源过滤配置怎么用?resource filtering详解与避坑指南

资源过滤的工作原理

Maven处理资源文件的组件叫maven-resources-plugin,它在process-resources阶段把src/main/resources下的文件复制到target/classes目录。如果某个资源开启了filtering,复制过程就会多一步文本替换:Maven会扫描文件内容,把所有${...}形式的占位符替换成对应的属性值。这些属性值的来源包括pom.xml中的properties节点、settings.xml中的属性、系统属性以及环境变量。

理解这一点很关键:filtering本质上是字符串替换,Maven并不关心文件类型。这意味着如果你对一个二进制文件开启了过滤,Maven会把它当文本读入再写出,编码转换过程可能破坏文件内容。这也是为什么默认配置下filtering是关闭的,需要显式声明。

占位符替换的优先级从高到低大致是:命令行传入的属性(如mvn -Djdbc.url=xxx)、profile中定义的属性、pom.xml的properties属性、settings.xml属性、系统属性和环境变量。掌握这个顺序有助于排查属性被意外覆盖的问题。

pom.xml中的基础配置写法

先看一个最小可用的配置。在build节点下声明resources,指定哪些目录需要处理、哪些文件开启过滤:

<build>
    <resources>
        <!-- 第一组:配置文件开启过滤,占位符会被替换 -->
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>*.properties</include>
                <include>*.yml</include>
                <include>*.xml</include>
            </includes>
        </resource>
        <!-- 第二组:二进制文件关闭过滤,原样复制 -->
        <resource>
            <directory>src/main/resources</directory>
            <filtering>false</filtering>
            <excludes>
                <exclude>*.properties</exclude>
                <exclude>*.yml</exclude>
                <exclude>*.xml</exclude>
            </excludes>
        </resource>
    </resources>
</build>

这里有一个非常容易踩的坑:一旦你在pom.xml中显式声明了resources节点,Maven的默认资源处理规则就被完全覆盖了。如果只写了第一组配置,那么properties、yml、xml以外的文件(比如图片、字体)都不会被复制到target/classes,运行时会报找不到资源的错误。所以上面的第二组配置不是可有可无的,它负责把剩下的文件原样拷贝进去。

两个resource节点匹配同一个目录并不冲突,Maven会依次处理,按includes和excludes的匹配结果决定每个文件走哪条规则。文件匹配支持通配符,*.properties匹配一级目录,**/*.properties匹配任意层级子目录,写的时候要注意这个差别。

自定义属性与占位符替换实战

定义了过滤规则之后,还需要提供属性来源。最常见的做法是在pom.xml的properties节点中定义变量,然后在配置文件中用占位符引用。假设src/main/resources下有一个jdbc.properties,内容如下:

jdbc.url=${jdbc.url}
jdbc.username=${jdbc.username}
jdbc.password=${jdbc.password}

在pom.xml中补充属性定义:

<properties>
    <jdbc.url>jdbc:mysql://127.0.0.1:3306/demo</jdbc.url>
    <jdbc.username>root</jdbc.password>
    <jdbc.password>123456</jdbc.password>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

执行mvn clean package后,打开target/classes下的jdbc.properties,就能看到占位符已经被替换成实际值。需要注意的是${project.version}、${project.artifactId}这类内置属性可以直接使用,不用额外定义。另外建议始终设置project.build.sourceEncoding为UTF-8,否则中文注释在过滤替换后可能变成乱码。

还有一个细节:如果某个属性没有定义,Maven默认会让占位符原样保留在文件中,并不会报错。这既是好事也是隐患,好处是不影响构建,坏处是问题被延迟到运行时才暴露。可以在构建日志中搜索相关文件名确认过滤是否执行,也可以直接查看target/classes下的产物验证替换结果。

结合profile实现多环境打包

资源过滤真正的价值在多环境场景。开发、测试、生产三个环境的数据库地址不同,不可能维护三份配置文件手动切换。配合maven profile可以做到按需替换:

<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <jdbc.url>jdbc:mysql://127.0.0.1:3306/dev_db</jdbc.url>
            <env.label>开发环境</env.label>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <jdbc.url>jdbc:mysql://10.0.1.100:3306/prod_db</jdbc.url>
            <env.label>生产环境</env.label>
        </properties>
    </profile>
</profiles>

打包时通过mvn package -P prod激活生产环境的profile,配置文件中的占位符就会替换成生产环境的值。如果配合spring-boot-maven-plugin使用,还可以结合@...@分隔符避免和Spring自身的${...}占位符冲突,只需在resource节点中配置delimiters即可。

最后提醒一点:Spring Boot项目从2.x开始,其父pom已经默认对application.properties和application.yml开启了过滤,且分隔符是@符号。如果你在自己的pom里再叠加一套${}过滤规则,容易出现双重替换或者互相干扰,建议先查看有效pom(mvn help:effective-pom)确认已有的资源配置,再决定如何追加自己的规则,避免重复声明带来的奇怪问题。

Maven资源过滤pom.xml配置resource filtering修改时间:2026-09-11 02:46:30

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0911/54408.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。