本篇文章重点针对这几个问题进行讲解:
这个插件只要我们编译代码就会用到该插件,就算我们项目没有声明该插件也照样会使用到,怎么证明呢?
我们可以在一个新的maven项目,不添加任何依赖,然后使用mvn clean install
Maven 默认为一些核心的生命周期阶段绑定了插件目标,当用户调用这些阶段时,对应的插件目标就会自动执行相应的任务。其中maven-resources-plugin的resources和testResources两个目标,绑定到了default生命周期的process-resources和process-test-resources两个阶段上。
关于生命周期不是很理解的可以看一下这篇文章,本篇不过多介绍:https://blog.csdn.net/weixin_43888891/article/details/130756192
作用:他的作用是将项目的资源(resources目录下)目录的文件复制到输出目录(target),输出目录又分为了两个,一个是测试的输出目录,一个是主资源的。所以对应了process-resources和process-test-resources两个阶段上,当然一般测试目录并没有资源目录。
什么是资源文件?
.java文件在运行的时候需要通过JRE编译成.class文件,然后放到target目录,然后本地启动项目的时候,jvm运行target目录下的编译过后的.class代码文件,
而资源文件就是不属于.java文件,那也就意味着不需要参与编译工作,但是运行的时候又依赖与他。这时候就需要通过maven-resources-plugin插件将其放到编译后的路径。这样我们项目启动的时候资源文件才能被使用。这也就是我们有时候项目经常会出现明明代码当中有这个文件,但是运行却说找不到文件的原因。
假如对生命周期了解的,看下图应该很容易就明白插件的作用了:
官网介绍:https://maven.apache.org/plugins/maven-resources-plugin/
既然插件是copy资源文件那必然涉及到文件的编码,可以选择的编码有ASCII, UTF-8 或者 UTF-16,设置编码的方式有两种
第一种:使用properties标签声明project.build.sourceEncoding,声明好后,插件当中的
标签会取这个编码
<project ...>
...
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
...
properties>
..
project>
第二种通过插件配置:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-resources-pluginartifactId>
<version>3.3.1version>
<configuration>
...
<encoding>UTF-8encoding>
...
configuration>
plugin>
plugins>
...
build>
...
project>
注意:只要官网当中提到了可以使用${…}的方式配置,那么我们就可以不声明插件,可以直接在properties当中配置。
resources标签其实就是maven-resources-plugin的配置,主要用来配置资源目录的
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resourcesdirectory>
<filtering>filtering>
<includes>
<include>include>
includes>
<excludes>
<exclude>exclude>
excludes>
resource>
<resource>
...
resource>
resources>
build>
指定资源文件目录
指定资源文件目录中,仅包含哪些文件被打包
指定资源文件目录中,仅哪些文件不被打包
是一个bool值,默认值为false。指定打包时的配置文件中是否进行变量替换所谓默认配置就是在项目当中不设置resources标签,他默认生效的
maven项目默认继承了一个父pom.xml,配置主要包含了如下,其中一些配置就是对maven-resources-plugin插件的配置:
关于如何查看默认继承的pom配置,感兴趣的可以看这一篇文章:https://blog.csdn.net/weixin_43888891/article/details/130483451
<build>
<directory>${project.basedir}/targetdirectory>
<outputDirectory>${project.build.directory}/classesoutputDirectory>
<finalName>${project.artifactId}-${project.version}finalName>
<testOutputDirectory>${project.build.directory}/test-classestestOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/javasourceDirectory>
<scriptSourceDirectory>${project.basedir}/src/main/scriptsscriptSourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/javatestSourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resourcesdirectory>
resource>
resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resourcesdirectory>
testResource>
testResources>
build>
比如outputDirectory就是maven-resources-plugin插件当中的配置如下:
springboot项目一般我们都会继承一个spring-boot-starter-parent,而他的pom当中就默认给我们做了一些resources插件的配置:
像这些resources标签的都是resources插件的配置,关于这个配置起到了什么作用后面会讲!
除此之外pluginManagement当中还存在resources插件的配置,如下:
假如我们项目没有继承spring-boot-starter-parent那么我们的项目默认继承了一个父pom,resources默认配置如下:
<resources>
<resource>
<directory>${project.basedir}/src/main/resourcesdirectory>
resource>
resources>
假如继承了spring-boot-starter-parent,那么我们的的项目resources默认配置如下,他会将maven默认配置给替换掉:
<resources>
<resource>
<directory>${basedir}/src/main/resourcesdirectory>
<filtering>truefiltering>
<includes>
<include>**/application*.ymlinclude>
<include>**/application*.yamlinclude>
<include>**/application*.propertiesinclude>
includes>
resource>
<resource>
<directory>${basedir}/src/main/resourcesdirectory>
<excludes>
<exclude>**/application*.ymlexclude>
<exclude>**/application*.yamlexclude>
<exclude>**/application*.propertiesexclude>
excludes>
resource>
resources>
这里需要注意一点:假如我们项目当中去声明resources标签,那么他会将继承的父类当中的resources标签给替换掉,说白了就是重写的会覆盖继承的
关于这个标签官网也有叙述:https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html
filtering默认为false,作用是是否允许指定任意文件可以以${...}
or @...@
的语法来提取pom.xml当中的配置。
用法示例:
1.资源文件中使用${keyword}占位符来定义变量, 如src/main/resouces/application.properties:
2.这时候可以在pom.xml文件中定义变量的取值
3.如果需要对配置文件中变量进行替换实际值,就需要开启
,该值设置为true。这里使用了includes标签指定了文件,也就是允许application.properties文件读取变量值。
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<filtering>truefiltering>
<includes>
<include>application.propertiesinclude>
includes>
resource>
resources>
build>
4.执行mvn clean package -DskipTests
打包,然后打开target/classes目录当中查看资源文件,会发现使用 @...@
取值成功了,而${...}
没有成功。
这个替换值是maven-resources-plugin插件的功能,其实我们不需要打包也可以测试,直接通过调用改插件的目标即可:
mvn resources:resources
原因:这是因为我这个项目继承了spring-boot-starter-parent,而springboot的xml当中有一个这个标签@...@
,因为spring害怕和其他语法有冲突,所以使用了这个配置。
我们也可以通过手动声明来覆盖springboot父类的配置,这样便可以通过${...}
语法进行取值了。
<properties>
<resource.delimiter>${*}resource.delimiter>
properties>
5.通过命令进行指定变量的值:mvn clean package -DskipTests -Dusername="lisi"
注:命令的优先级要高于pom当中配置的变量值
6.另, 变量的定义可以不放在pom里, 也可以指定其他文件, 通过build.filters.filter配置即可. 示例:
<build>
<filters>
<filter>src\main\resources\filters_file.propertiesfilter>
filters>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<filtering>truefiltering>
<includes>
<include>application.propertiesinclude>
includes>
resource>
resources>
build>
没有必要使用变量取值的,千万不要将filtering设置为true,针对于这一点官网也明确指出二进制文件一定不要过滤,之前我遇到过一个bug就是resources文件夹当中存放有Excel模板,导出模板后发现是乱码的,但是通过源代码打开Excel就是正常的,原因就是将文件给进行过滤了。导致编译过后target当中的Excel都是乱码的。
关于这个标签官网也有叙述:https://maven.apache.org/plugins/maven-resources-plugin/examples/include-exclude.html
我们来看springboot默认的配置,针对于上面一个环节我们已经搞清楚了,但是下面的呢,为什么允许了,后面又使用exclude给过滤掉了呢?
其实实际开发当中很多人对这都是不理解,配置起来也是一顿乱配置。多读两遍我图片上写的注释,一旦理解了,就彻底懂了!
include和excludes标签也可以同时出现在一个resource当中,例如如下:
将以txt结尾的文件copy到target,需要排除掉文件名当中携带test的。
**/
代表的是根目录,/src/main/resources 和 /src/main/java 这两个都属于根目录,一个*
可以代表一个占位符,可以是多个字母组成的
<build>
...
<resources>
<resource>
<directory>src/my-resourcesdirectory>
<includes>
<include>**/*.txtinclude>
includes>
<excludes>
<exclude>**/*test*.*exclude>
excludes>
resource>
...
resources>
...
build>
关于resources标签当时我还专门写了一篇关于这个的文章,当时其实是似懂非懂,只能说通过亲自试验得出来了一些结论:https://blog.csdn.net/weixin_43888891/article/details/122406081
两篇文章结合着看基本上就可以彻底掌握了!
官网相关配置详解:https://maven.apache.org/plugins/maven-resources-plugin/resources-mojo.html
maven-resources-plugin插件是maven内置插件,我们就算项目不声明,调用的时候也会访问。一般项目当中本身也就不需要声明,基本上都是通过resources标签来控制资源文件的。
springboot父pom默认配置如下:
这是我当时在公司遇到的一个关于该插件的bug:https://blog.csdn.net/weixin_43888891/article/details/130089503
在彻底掌握了resources之后才发现原来公司很多开发都是一顿乱配置,包括我在内,哈哈哈
当时就是使用了filtering为true然后导致Excel压缩过后打不开了,然后添加了如下配置
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-resources-pluginartifactId>
<version>3.2.0version>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>xlsnonFilteredFileExtension>
<nonFilteredFileExtension>xlsxnonFilteredFileExtension>
nonFilteredFileExtensions>
configuration>
plugin>
这里有一点需要注意,springboot在父pom的pluginManagement设置了maven-resources-plugin,而我们又在项目当中声明了maven-resources-plugin,最终他生效的是父pom+我们声明的配置:
通过mvn help:effective-pom
命令即可查看生效的pom