1.背景

SpringBoot打包的Jar包,一般少则几十M,大则上百或者几百M。如果用Jar包部署的话,Jar包上传到服务器环境,视带宽情况,快则十几秒到几十秒不等。每次都需要上传一个上百M的大文件,影响效率。如果是需要走公网上传到云服务器,还要耗费不少带宽成本。

Jar包里容量最大的是依赖包(dependencies),除去依赖的Jar包一般就几十几百K,而依赖包一般来说极少有变化,如果构建Jar的时候,把依赖包分离开,当依赖没变化,只更新Jar包,依赖项有变化时,再一起上传更新。这样,大部分构建部署,只需要上传几百K的Jar包到服务器。效率会大大提高。

2.实现流程

相关版本说明:

  1. Maven3.5
  2. SpringBoot2.4.2

2.1.配置ClassPath路径

利用maven-jar-plugin插件,把lib文件夹配置成ClassPath。

  1. <plugin>
  2. <groupId>org.apache.maven.plugins</groupId>
  3. <artifactId>maven-jar-plugin</artifactId>
  4. <configuration>
  5. <archive>
  6. <manifest>
  7. <addClasspath>true</addClasspath>
  8. <classpathPrefix>lib/</classpathPrefix>
  9. </manifest>
  10. <manifestEntries>
  11. <Class-Path>./</Class-Path>
  12. </manifestEntries>
  13. </archive>
  14. </configuration>
  15. </plugin>

2.2.配置Jar包构建信息

使用spring-boot-maven-plugin插件构建Jar包

  1. <plugin>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-maven-plugin</artifactId>
  4. <configuration>
  5. <fork>true</fork>
  6. <addResources>true</addResources>
  7. <!--手动设置构建需要加入的依赖,只有配置的依赖才会加入。-->
  8. <includes>
  9. <!--配置一个不存在的groupId,这样就不会引入任何依赖,jar包就只包含代码文件-->
  10. <include>
  11. <groupId>not-exists</groupId>
  12. </include>
  13. <!--如果是多模块项目,其他模块需要手动添加下面-->
  14. </includes>
  15. </configuration>
  16. </plugin>

2.3.把依赖拷贝到指定路径

使用maven-dependency-plugin插件把依赖包拷贝到上述步骤配置的路径下

  1. <plugin>
  2. <groupId>org.apache.maven.plugins</groupId>
  3. <artifactId>maven-dependency-plugin</artifactId>
  4. <executions>
  5. <execution>
  6. <id>copy-dependencies</id>
  7. <phase>prepare-package</phase>
  8. <goals>
  9. <goal>copy-dependencies</goal>
  10. </goals>
  11. <configuration>
  12. <outputDirectory>${project.build.directory}/lib</outputDirectory>
  13. </configuration>
  14. </execution>
  15. </executions>
  16. </plugin>

2.4.完整构建配置

  1. <build>
  2. <resources>
  3. <resource>
  4. <directory>src/main/resources</directory>
  5. <filtering>true</filtering>
  6. </resource>
  7. </resources>
  8. <plugins>
  9. <!-- 自定义ClassPath路径 -->
  10. <plugin>
  11. <groupId>org.apache.maven.plugins</groupId>
  12. <artifactId>maven-jar-plugin</artifactId>
  13. <configuration>
  14. <!-- 把构建根目录的lib文件夹配置成ClassPath路径 -->
  15. <archive>
  16. <manifest>
  17. <addClasspath>true</addClasspath>
  18. <classpathPrefix>lib/</classpathPrefix>
  19. </manifest>
  20. <manifestEntries>
  21. <Class-Path>./</Class-Path>
  22. </manifestEntries>
  23. </archive>
  24. </configuration>
  25. </plugin>
  26. <!--配置Jar包构建信息-->
  27. <plugin>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-maven-plugin</artifactId>
  30. <configuration>
  31. <fork>true</fork>
  32. <addResources>true</addResources>
  33. <!--手动设置构建需要加入的依赖,只有配置的依赖才会加入。-->
  34. <includes>
  35. <!--配置一个不存在的groupId,这样就不会引入任何依赖,jar包就只包含代码文件-->
  36. <include>
  37. <groupId>not-exists</groupId>
  38. </include>
  39. <!--如果是多模块项目,其他模块需要手动添加下面-->
  40. </includes>
  41. </configuration>
  42. </plugin>
  43. <!--把依赖拷贝到Lib路径-->
  44. <plugin>
  45. <groupId>org.apache.maven.plugins</groupId>
  46. <artifactId>maven-dependency-plugin</artifactId>
  47. <executions>
  48. <execution>
  49. <id>copy-dependencies</id>
  50. <phase>prepare-package</phase>
  51. <goals>
  52. <goal>copy-dependencies</goal>
  53. </goals>
  54. <configuration>
  55. <outputDirectory>${project.build.directory}/lib</outputDirectory>
  56. </configuration>
  57. </execution>
  58. </executions>
  59. </plugin>
  60. </plugins>
  61. </build>

2.5.最终效果

执行mvn clean package,targe目录如下:

SpringBoot构建Jar包实现依赖包分离 - 图1

SpringBoot构建Jar包实现依赖包分离 - 图2

可以看到,Jar包只有293K大小,50M的依赖包已经移到根目录下的lib文件夹,由于已经配置lib文件夹为ClassPath,因此直接运行jar包就可以启动应用。

SpringBoot构建Jar包实现依赖包分离 - 图3