java - 10 SpringBoot项目使用maven,如何减小自己的jar大小?
问题描述
我们的项目有大约 10 个 SpingBoot 模块,我们使用 maven 来管理依赖关系。10罐大小约2G。最近我们需要减小 jar 的大小以方便我们的客户部署。
我有一个想法,提取常见的jar(不经常更改),例如spring-.jar,spring- boot- .jar,jodd*.jar,elasticsearch等。只要> = 2个项目使用相同的依赖,一个我们称之为“普通罐子”的罐子。
如果你知道一些有用的解决方案,请告诉我。
我尝试了下方法,但遇到了一些麻烦。
新建一个程序作为计算项目之间常见 artifactId 的工具,最后我得到了一个 artifactId 列表。
新建一个maven模块来打包常用依赖,最后得到一个包含常用jar文件的lib文件。我将它命名为“common-lib”。
更改旧项目的 pom 文件如下:
- 添加 maven-jar-plugin 让我的项目加载公共库的类
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.xx.MyManagerApplication</mainClass>
<useUniqueVersions>false</useUniqueVersions>
<addClasspath>true</addClasspath>
<!--classpathPrefix let Manifest.MF's Class-Path add the 'common-lib' as prefix-->
<classpathPrefix>common-lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
- 更改 spring-boot-maven-plugin 的配置如下:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.xx.MyManagerApplication</mainClass>
<layout>ZIP</layout>
<excludeArtifactIds>
spring-webmvc,
spring-web,
spring-tx,
spring-security-rsa,
spring-security-crypto,
spring-jdbc,
spring-jcl,
spring-expression,
spring-core,
spring-context,
spring-cloud-starter-zipkin,
...ellipsis
</excludeArtifactIds>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
最后我的项目的 jar lib 只包含没有 common-lib。并且jar大小减少到900K(过去105M)。它大大减小了罐子的大小。
- 将myproject.jar和common-lib放在同一目录下
- 公共库
- 许多罐子...
- 我的项目.jar
然后启动我的项目
java -Dspring.profiles.active=dev -Dspring.config.location=application.yml -jar my-project.jar
然而它并没有像我想象的那样工作。而是在控制台中显示错误消息
[2020-12-01 15:54:19.252+0800]-[foundation-manager]-[1;31m[ERROR][0;39m-[]-[8340:main] o.s.boot.SpringApplication 837 : Application run failed
java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.springframework.boot.BeanDefinitionLoader.<init>(BeanDefinitionLoader.java:84)
at org.springframework.boot.SpringApplication.createBeanDefinitionLoader(SpringApplication.java:745)
at org.springframework.boot.SpringApplication.load(SpringApplication.java:685)
at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:381)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:305)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:137)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:208)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:104)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:70)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:74)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:338)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:297)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230)
at com.yealink.foundation.manager.app.FoundationManagerApplication.main(FoundationManagerApplication.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:593)
Caused by: java.lang.ClassNotFoundException: groovy.lang.GroovyObject
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 40 common frames omitted
groovy 的 lib 不是 common-lib,它存在于项目的 jar 中。原因是第 2 步我更改了 Manifest.MF 文件,所以 jvm 在 common-lib/groovy.xxx.jar 中找到 groovy 的库?
如果你知道一些有用的解决方案,请告诉我。
解决方案
我做了一些与你的设置类似的事情,但在我的情况下,它是为了优化 Docker 推送。
我的 spring-boot-maven-plugin 是不同的:
看看以下内容是否对您有帮助:
<!-- This plugin copies different external dependencies into separate folders
that are later used to build an optimized Docker image -->
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-external-project-dependencies</id>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<excludeGroupIds>com.susan</excludeGroupIds>
<outputDirectory>${project.build.directory}/external-dependencies</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-hello-cloud-platform-dependencies</id>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<includeGroupIds>com.susan.hello.cloud-platform</includeGroupIds>
<outputDirectory>${project.build.directory}/cloud-dependencies</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-susan-project-dependencies</id>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<includeGroupIds>com.susan.ca.cc</includeGroupIds>
<outputDirectory>${project.build.directory}/susan-dependencies</outputDirectory>
</configuration>
</execution>
<execution>
<id>submodule-dependencies</id>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<includeGroupIds>com.susan</includeGroupIds>
<excludeGroupIds>com.susan.ca.cc,com.susan.hello.cloud-platform</excludeGroupIds>
<outputDirectory>${project.build.directory}/submodule-dependencies</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>build-info</id>
<goals>
<goal>build-info</goal>
</goals>
</execution>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.susan.hello.whee.HelloApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
复制 /susan/target/external-dependencies /lib
复制 /susan/target/hello-dependencies /lib
复制 /susan/target/cloud-dependencies /lib
复制 /susan/target/submodule-dependencies /lib
app.jar 在 /lib 之外
java - jar app.jar
这一切看起来都和你做的一样,我唯一能想到的就是 spring-boot-maven-plugin 设置。
推荐阅读
- python - 如何合并多个 mp3 文件?
- css - 在woocommerce中更改类别描述的字体大小
- c++ - 激励“内联”说明符的真实世界示例?
- soap - IBM WAS JMX 使用 SOAP 协议与 JConsole 连接
- php - 将今天与 db 中的日期进行比较,并检查 30 天前的天气
- cmake - 将环境变量传递给 CMake execute_process 中的 COMMAND
- csv - 不在 vue.js 中上传 CSV 文件
- java - 如何使用 Selenium 和 Java 获取跨度类值
- json - 如何在 XSLT 中将 XML 转换为 Json?
- python - 如何调用包含另一个方法的另一个类方法?