Maven 打包依赖外置 需求背景 最近发现公司的项目都是本地打包、上传到服务器,这些包动辄几十 M 甚至上百 M,而且因为没有做 CI/CD,有时网络状况不好每次上传都要几十分钟,服务数量太多时候部署也是一件很头疼的事。
实际上这些依赖大部分都是类似甚至可以共同使用的(比如 Spring 系列的包),完全没有必要在每个程序编译时都带上这些依赖。
因此可以考虑把这部分依赖包整理出来,存放在服务器上作为服务的共享库。
一般部署 以一个简单的 Spring Boot 应用为例,只有一个类文件 DemoApplication.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestController("/") @SpringBootApplication public class DemoApplication { @GetMapping public String get () { return "Hello, World!" ; } public static void main (String[] args) { SpringApplication.run(DemoApplication.class, args); } }
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build >
打包后发现哪怕只有一个接口,可以单独运行的 jar 包占据 16M 之大:
1 2 3 4 $ mvn clean package # ... $ ll -h demo-0.0.1-SNAPSHOT.jar -rw-r--r-- 1 yipwinghong 197609 16M 10月 8 22:23 demo-0.0.1-SNAPSHOT.jar
解压 demo-0.0.1-SNAPSHOT.jar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ ll -h BOOT-INF/lib/ total 16M -rw-r--r-- 1 ywh 197609 67K 8月 2 18:14 jackson-annotations-2.11.2.jar -rw-r--r-- 1 ywh 197609 344K 8月 2 18:16 jackson-core-2.11.2.jar -rw-r--r-- 1 ywh 197609 1.4M 8月 2 18:36 jackson-databind-2.11.2.jar -rw-r--r-- 1 ywh 197609 34K 8月 2 19:44 jackson-datatype-jdk8-2.11.2.jar -rw-r--r-- 1 ywh 197609 109K 8月 2 19:44 jackson-datatype-jsr310-2.11.2.jar -rw-r--r-- 1 ywh 197609 9.1K 8月 2 19:44 jackson-module-parameter-names-2.11.2.jar -rw-r--r-- 1 ywh 197609 25K 8月 2 2019 jakarta.annotation-api-1.3.5.jar -rw-r--r-- 1 ywh 197609 233K 8月 26 2019 jakarta.el-3.0.3.jar -rw-r--r-- 1 ywh 197609 4.5K 12月 16 2019 jul-to-slf4j-1.7.30.jar -rw-r--r-- 1 ywh 197609 286K 5月 10 12:07 log4j-api-2.13.3.jar -rw-r--r-- 1 ywh 197609 18K 5月 10 12:10 log4j-to-slf4j-2.13.3.jar # ...
只因其中包含了大量的 jar 包…= =
依赖外置 解决方式是打包时只包含自己的代码,而把依赖包导出。
pom.xml 改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > <configuration > <mainClass > com.ywh.demo.DemoApplication</mainClass > <layout > ZIP</layout > <includes > <include > <groupId > nothing</groupId > <artifactId > nothing</artifactId > </include > </includes > </configuration > </plugin > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-dependency-plugin</artifactId > <executions > <execution > <id > copy-dependencies</id > <phase > package</phase > <goals > <goal > copy-dependencies</goal > </goals > <configuration > <outputDirectory > ${project.build.directory}/lib/ </outputDirectory > </configuration > </execution > </executions > </plugin > </plugins > <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 >
重新打包:
查看 target 输出的内容,可见 jar 包只剩下 121K 了,依赖包被导出到 target/lib 下(正好占据 16M,与之前的整包基本一致),应该没什么问题。
1 2 3 4 5 6 7 8 9 $ ll -h target/demo-0.0.1-SNAPSHOT.jar -rw-r--r-- 1 yipwinghong 197609 121K 10月 8 22:36 demo-0.0.1-SNAPSHOT.jar $ ll -h target/lib/ total 16M -rw-r--r-- 1 ywh 197609 67K 10月 8 21:01 jackson-annotations-2.11.2.jar -rw-r--r-- 1 ywh 197609 344K 10月 8 21:01 jackson-core-2.11.2.jar -rw-r--r-- 1 ywh 197609 1.4M 10月 8 21:02 jackson-databind-2.11.2.jar -rw-r--r-- 1 ywh 197609 34K 10月 8 21:01 jackson-datatype-jdk8-2.11.2.jar # ...
但是因为缺少必要的依赖,这个包是不能跑起来的:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ java -jar target/demo-0.0.1-SNAPSHOT.jar Exception in thread "main" java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) at org.springframework.boot.loader.Launcher.launch(Launcher.java:107) at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:466) Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/SpringApplication at com.ywh.demo.DemoApplication.main(DemoApplication.java:18) ... 8 more
要部署程序,在启动参数 -Dloader.path
指定依赖包导出的路径即可:
1 2 3 4 5 6 7 8 9 10 11 12 $ java -Dloader.path=target/lib/ -jar target/demo-0.0.1-SNAPSHOT.jar . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.4.RELEASE) 2020-10-08 22:45:07.138 INFO 19232 --- [ main] com.ywh.demo.DemoApplication : Starting DemoApplication v0.0.1-SNAPSHOT on DESKTOP-N02L3UQ with PID 19232 (C:\Project\other-project\demo\target\demo-0.0.1-SNAPSHOT.jar started by yipwinghong in C:\Project\other-project\demo) # ...
如果希望单独导出这些包到指定路径 ${LIB_PATH}
,可以执行:
1 mvn dependency:copy-dependencies -DoutputDirectory=${LIB_PATH}
总结 一般来说一个项目整体框架确定后,引入的依赖包不会有太大的改动,因此固定存放在服务器上的某个路径即可。
如果只是修改业务逻辑、重新部署时没有必要把依赖包也一并带上;
但如果涉及到 pom 文件结构、依赖的变更,则需要修改原来的 lib。