Maven资源打包到jar包外

302 阅读2分钟

       最近在学习spring boot,众所周知,spring boot可以方便地打包成jar,直接将运行容器打包进去后,运行jar即可启动,spring boot也提供了maven插件spring-boot-maven-plugin可以方便地将项目进行统一打包。但是让人不解的事,不知道为什么spring-boot-maven-plugin插件是将项目所有内容都一起打包进一个jar包中,也即项目依赖的各种spring boot的其它jar包也一起打包到最终项目jar包内,这就导致最后生成的jar包非常大,这无疑给一些相对中小型的项目来说带来了不友好的体验,本来自身的项目不大,直接打包上传自己项目的jar包即可(上传到运行服务器),但是统一打包到一个jar里,无疑就要上传一个更大的包了。一直在寻思怎样能够将spring boot中的其它依赖包及项目资源(即resources目录下的配置文件)单独放到jar包外,在网上搜索了一下,相关解答很多,但是都不太符合我的情况,经过自己的摸索,得到一些新的知识,遂记录如下。

       首先是通过pom文件的resources元素进行资源排除,这里网上很多人没有说清楚的是,其实resources元素是控制资源文件生成的情况的,注意是生成,并不是打包,这个时候pom的执行周期还没有到打包阶段。什么意思呢,就是resources是设置要生成到最后classes目录下的资源文件,或排除的资源文件。也即如果pom有resources元素排除了一些文件,那么在生成的calsses下就不会有这些文件生成。

    <resources>      <resource>        <directory>src/main/resources</directory>        <excludes>          <exclude>*.properties</exclude>          <exclude>*.temp</exclude>        </excludes>        <targetPath>${project.build.directory}/resources</targetPath>      </resource>    </resources>

       如果在classes下没有生成这个文件, 后面在打包jar阶段时候因为是基于classes文件夹下编译后的代码做jar打包的,所以如果在resources时没有生成,那么自然就不会打包进去。

       这里注意resources元素只是针对资源文件的操作,并不会对依赖的其它jar包进行处理。对于依赖的jar包处理接下来会说。可能有时候会觉得,既然resources元素有这种功能,那直接用这个功能剔除资源文件不打包进jar里就可以了。但是这个对于用不同的人来说有同步的需求,这是需要注意的,在classes下不生成文件对于一些直接运行的IDE来说可能是有副作用的。比如我是用VSCode开发的,在调试运行程序时,如果用resources排除文件,那么就会出现在VSCode下直接F5调试运行时报找不到配置文件,可能就需要单独在VSCode的launch.json中配置加载配置文件目录。

       而另外一种方式就是不用resources元素,也不用spring boot提供的maven插件,而是使用如下配置进行打包,这样就可以将jar和配置文件打包到另外的目录下,而VSCode调试时也不会出现加载不到配置文件的情况:

    <!-- 编译插件 -->    <plugins>      <!-- jar包打包插件 -->      <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-compiler-plugin</artifactId>        <configuration>          <release>13</release>          <encoding>UTF-8</encoding>        </configuration>      </plugin>      <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-jar-plugin</artifactId>        <configuration>          <archive>              <manifest>                  <addClasspath>true</addClasspath>                  <classpathPrefix>lib</classpathPrefix>                  <mainClass>com.samugao.pipo.App</mainClass>              </manifest>              <!-- 增加打包jar中manifest里的class-path,因为resources单独放到一个目录
                所以要将其加入classPath,否则可能会加载不到 -->              <manifestEntries>                  <Class-Path>resources/</Class-Path>              </manifestEntries>          </archive>          <!-- 剔除一些不必要的文件夹、文件后续单独拷贝到一个单独文件夹 -->          <excludes>
             <!-- 这里剔除文件夹和文件的通配格式和我在网上搜到的情况不太一样 -->             <exclude>**/config</exclude>             <exclude>/*.*</exclude>          </excludes>        </configuration>      </plugin>      <!-- 将引用依赖的jar包单独拷贝到lib目录下,不打包到一个jar包内 -->      <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-dependency-plugin</artifactId>        <executions>           <execution>              <id>copy</id>              <phase>install</phase>              <goals>                 <goal>copy-dependencies</goal>              </goals>              <configuration>                <outputDirectory>${project.build.directory}/lib</outputDirectory>              </configuration>           </execution>        </executions>      </plugin>      <!-- 将资源目录下的文件拷贝到资源目录 -->      <plugin>        <artifactId>maven-resources-plugin</artifactId>        <executions>           <execution>            <id>copy-resources</id>            <phase>package</phase>            <goals>               <goal>copy-resources</goal>            </goals>            <configuration>              <resources>                <resource>                   <directory>src/main/resources</directory>                </resource>              </resources>              <outputDirectory>${project.build.directory}/resources</outputDirectory>            </configuration>           </execution>        </executions>      </plugin>    </plugins>