关于maven打包时, 资源文件没有被打包进来的问题
在之前的一篇文章mybatis看这一篇就够了当中,提到过,在使用mybatis时,有时候需要把编写了SQL语句的XML文件,和Java类文件放在一起,如如果不加配置,用maven进行打包时,默认不会将src/main/java目录下的XML文件打包进去。因为src/main/java被设定为了源码目录,默认只会将其中的Java文件进行编译打包。即,默认打包得到的结果如下可以看到com.exampl
问题起因
在之前的一篇文章mybatis看这一篇就够了当中,提到过,在使用mybatis时,有时候需要把编写了SQL语句的XML文件,和Java文件放在同一个目录下,如
如果不加配置,用maven进行打包时,默认不会将src/main/java
目录下的XML文件打包进去。因为src/main/java
被设定为了源码目录,默认只会将其中的Java文件进行编译打包。
即,默认打包得到的结果如下
可以看到com.example.mp.mappers
包下没有XML文件
我们可以配置pom.xml
中的resources
标签,指定打包时,加入src/main/java
下面的XML文件,pom.xml
如下
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
这样配置后,再次打包,src/main/java
目录下的XML文件就会被打包进来了
问题出现
然而,今天在一个SpringBoot项目中测试mybatis-plus的demo时,发现,若pom.xml
中增加了这一个自定义的resources
标签配置,会覆盖掉默认的resources
打包配置,使得src/main/resources
目录下的文件无法打包进来,从而运行时因为缺少application.yml
等资源文件而报错。
假设我们有一个SpringBoot的项目,目录结构如下
我们的pom.xml
按照上面所说,配置了扫描src/main/java
下面的XML文件。我们执行mvn clean package -DskipTests=true
进行打包。
根据maven的执行日志,看到maven的resources插件只打包了一个资源文件
我们查看打包后的target
目录
可以看到,src/main/java
下的XML文件被成功打包了进来。
但src/main/resources
下的资源文件全都没有被打包进来
此时运行该SpringBoot项目,因为缺失application.yml
,找不到配置的数据源,而报错
而如果我们在pom.xml
中去掉resources
标签的配置,即删掉
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
其他部分不变,再次打包
maven执行的日志显示,maven资源插件打包了3个资源文件
查看打包后的target
目录
src/main/resources
目录下的资源文件被成功打包进来了。而由于没有配置,src/main/java
下的XML文件就没有被打包。
由此可知,默认情况下,maven打包会将资源目录(一般是src/main/resources
)中的资源文件打包进去。
如何查看项目的资源目录呢?
IDEA左上角 File — Project Structure — Modules — 选中你的项目
可以看到,蓝色的文件夹就是源代码目录,右下角带着像金币一样图标的文件夹,就是资源目录,而绿色的是测试代码目录。
若要将某个目录设为资源目录,鼠标选中那个目录,在上方的Mark as
那一行,点击Resources
即可。
初步结论
上面说到,maven默认会将资源目录下的资源文件进行打包,而如果在pom.xml
中配置了resources
标签,则默认的资源打包策略就被覆盖掉了,只会打包resources
标签中配置的资源文件,所以,如果pom.xml
中配置了
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
则只会打包该配置指定的目录,不会打包src/main/resources
目录,即使它是项目的资源目录。
这一点需要特别注意!!!需要特别注意!!!特别注意!!!
解决方案呢?当然有,手动将src/main/resources
也添加到配置就可以了。按如下的pom.xml
配置,maven打包时,既能包含src/main/java
下的XML文件,也能包含资源目录(src/main/resources
)下面的资源文件
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
</build>
或者,把全部的资源文件,统一放在src/main/resources
目录下,这样无需额外配置pom.xml
。
问题回溯
然而,在一年前的这篇文章 -> mybatis看这一篇就够了 当中,提到过当把XML文件和java类放在一起时,可以通过增加pom.xml
的配置解决XML文件没有被打包的问题,当时增加了pom.xml
中的resources
配置,仅配置了扫描src/main/java
目录,但是src/main/resources
下的文件也被打包了进来。好像并没有出现这次遇到的这种问题。
我起初怀疑跟SpringBoot有关,但是,经过反复的测试,发现maven项目都会出现这种问题,并且我把mybatis看这一篇就够了这篇文章中当时使用的demo代码找到了,重新用maven进行打包测试,发现问题仍然出现。这时我就很困惑了,当时为什么没有问题?当时为什么就把src/main/resources
下的文件打包进来了?会不会和maven的版本,maven的插件版本等有关?
…(A FEW YEARS LATER)…
经过反反复复,反反复复的测试,我!终于复现了当时的情景!! 首先,运行mvn clean
将maven构建的文件全部删除,然后在pom.xml
中配置resources
标签仅扫描src/main/java
。
随后,我们不运行maven命令进行打包,而直接选中一个测试类,直接点击运行一个测试用例
由于项目还未编译打包,此时会触发IDEA的自动构建
构建完毕后,我们查看target
目录
发现src/main/java
中的XML文件没有被打包进来,而src/main/resources
下的资源文件倒是被打包了进来。根据我合理的猜测,IDEA的自动构建没有使用pom.xml
中build
标签下的配置,默认只是编译了源码目录下的java文件,并打包了资源目录下的资源文件。而此时我如果仅仅运行mvn package
命令,而不是mvn clean package
。由于没有运行mvn clean
,所以先前已经构建好的文件不会被删掉。于是mvn package
执行完毕后,src/main/java
下的XML文件也被添加了进来。
谜团解开
至此,谜团解开。使用maven进行打包,若pom.xml
中没有配置resources
标签,则会采用默认策略,打包资源目录(src/main/resources
)下的资源文件。若pom.xml
中配置了resources
标签,则完全以配置的为准。即,如果pom.xml
中的resources
标签只配置了扫描src/main/java
,则只会扫描src/main/java
,不会扫描src/main/resources
,即使后者已经被标记为项目的资源目录。
先前的,仅仅配置pom.xml
扫描src/main/java
下的XML文件,而src/main/resources
下的文件也打包了进来,这种情况,是因为一开始就进行过构建,src/main/resources
目录下的文件已经被打包了进来,而后续的打包并没有执行mvn clean
清除已有的文件。
所以,在使用mybatis的时候,mapper.xml文件,最好就统一放在src/main/resources
资源目录下,这样就无需额外配置pom.xml
。(其他资源文件也一样)。若实在需要把XML文件放在src/main/java
源码目录下,那么配置pom.xml
中的resources
标签时,一定要记得加上src/main/resources
,如下
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
</build>
(完)
都看到这了,一定是个小可爱,这么可爱的你,会给我一个赞的对吧?☺️
更多推荐
所有评论(0)