#java #spring-boot #maven
#java #spring-boot #maven
Вопрос:
в нашем проекте около 10 модулей SpingBoot, мы используем maven для управления зависимостями. размер 10 jar около 2G. в последнее время нам нужно уменьшить размер jar, удобный для развертывания нашим клиентом.
У меня есть идея, извлечь обычную jar (не очень часто меняемую), например spring-.jar , spring-boot-.jar , jodd *.jar, elasticsearch и т.д. Пока > = 2 проекта используют одну и ту же зависимость, которую мы назвали «common jar».
Если вы знаете какие-то полезные решения, пожалуйста, скажите мне.
Я пробовал использовать метод under, но столкнулся с некоторыми проблемами.
- Новая программа как инструмент для вычисления общего идентификатора артефакта между моими проектами, наконец, я получил список артефактов.
- Новый модуль maven для упаковки общих зависимостей, наконец, я получил документ lib, содержащий общие файлы jar. Я назвал его «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 моего проекта не содержит только common-lib. и размер jar уменьшается до 900 КБ (105 млн в прошлом). Это значительно уменьшает размер jar.
- Разместил myproject.jar и common-lib в том же каталоге
- common-lib
- много jar…
- myproject.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 не является обычной библиотекой, она существует в jar проекта. причина в том, что на шаге 2 я изменил манифест.MF-файл, чтобы jvm нашел библиотеку groovy в common-lib/groovy.xxx.jar ?
Если вы знаете какие-то полезные решения, пожалуйста, скажите мне.
Комментарии:
1. Каждый модуль `SpingBoot module` является автономным приложением? Или это только модуль, который используется конечным приложением? У вас есть более одного приложения Spring Boot? Используете ли вы многомодульную настройку? Можете ли вы создать пример проекта, который показывает, как создаются и взаимодействуют друг с другом модули вашего приложения? Исходя из того, что я читаю, ваша настройка казалась неправильной..
2. да, 10 приложений SpringBoot. Что не так с моей настройкой
3. Вы должны извлечь общие части в отдельные модули, что упрощает их повторное использование в качестве зависимостей, что уменьшает размер ваших результирующих файлов jar. Кроме того, я не понимаю, почему вы настроили spring-boot-maven-pugin для создания zip-файла, который исключает несколько вещей, потому что похоже, что вы пытаетесь самостоятельно обрабатывать зависимости, вместо того, чтобы позволить Maven выполнять свою работу… Кроме того, размер 2 гигабайт звучит так, что что-то не так? Пожалуйста, сделайте пример проекта, как выглядит ваш макет / pom… таким образом, это позволяет помочь…
Ответ №1:
Я сделал что-то похожее на вашу настройку, но в моем случае это было для оптимизации Docker push.
Мой 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>
COPY /susan/target/external-dependencies /lib
COPY /susan/target/hello-dependencies /lib
COPY /susan/target/cloud-dependencies /lib
COPY /susan/target/submodule-dependencies /lib
The app.jar находится за пределами /lib
java — jar app.jar
Все выглядит так же, как вы сделали, единственное, о чем я могу думать, это настройка spring-boot-maven-plugin.
Комментарии:
1. Спасибо! /lib, на мой взгляд, меняется не очень часто. при упаковке и развертывании мне не нужно копировать
2. Спасибо @SMA, это помогло мне консолидировать зависимые jar и узнать размер, который можно дополнительно проанализировать и исключить, если не требуется (зависимость mvn: анализ). 1
3. Рад помочь @prashant