background
With Spring Boot
the popularity of Spring Boot, more and more developers choose to use Spring Boot to publish web applications. Different from traditional War package release, Spring Boot
the entire project is packaged into a runnable Jar package (the so-called Flat Jar), resulting in a very large Jar package (usually 40M+). As is often the case with iterative releases these days, uploading such a huge file every time will waste a lot of time.
Let’s take a small project as an example to briefly describe the weight loss program used by my brother. Of course, if it is released on an intranet or the broadband you are using is extremely powerful, slimming down will not make much sense.
practice
Project Description
Create a new exercise project with the following structure:
ht-cdn
Static resources are stored (such as third-party js, css, images, etc.)ht-domain
Data entity definition in projectht-repository
Data layer interface and implementationht-service
Business logic interface and implementationht-ui-web
Web management
Which ht-ui-web
relies on ht-domain
, ht-repository
, ht-service
and implements a simple one GetMapping
.
Then package the project, the entire jar package is 24M like this
weight loss preparation
First we need to have a preliminary understanding of the Jar package. Its internal structure is as follows
example.jar
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-BOOT-INF
+-classes
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
When running this Jar, by default BOOT-INF/classes
, the class is loaded from BOOT-INF/lib
and the dependent Jar packages are loaded from. If you want to add external dependent Jar, you can LOADER_PATH
do it by setting environment variables.
In this way, we can confirm our ideas:
1. Extract those unchanged dependent Jar packages (such as spring dependencies, database drivers, etc., which will not be updated without upgrading the version) from the Flat Jar Leave to a separate directory, such as libs
2. When starting Jar, set to LOADER_PATH
use the libs from the previous step
In this way, the size of our final packaged jar package is greatly reduced, and we only need to update this streamlined version of Jar after each iteration.
Specific steps
slim down while packing
Usually we use it spring-boot-maven-plugin
for packaging. After reading the documentation, we found that the plug-in can be configured to ignore specific dependencies when packaging. The documentation is in spring-boot-maven-plugin .
First, back up the original dependencies: compile and package them into a Flat Jar, then unzip all the jar files BOOT-INF/lib
except ht-*
the related ones, and save them to libs
the directory.
Then modify pom.xml
the configuration as follows
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>ZIP</layout>
<!--去除在生产环境中不变的依赖-->
<excludeGroupIds>
org.springframework.boot,
org.springframework,
org.springframework.data,
org.mongodb,
com.github.0604hx,
com.fasterxml.jackson.core,
commons-beanutils,
commons-codec,
org.apache.commons,
org.apache.tomcat.embed,
org.hibernate,
org.slf4j,
com.jayway,
org.jboss,
com.alibaba,
com.fasterxml,
commons-collections,
ch.qos.logback,
org.scala-lang,
org.yaml,
org.jboss.logging,
javax.validation,
nz.net.ultraq.thymeleaf,
org.thymeleaf,
ognl,
org.unbescape,
org.javassist
</excludeGroupIds>
</configuration>
</plugin>
</plugins>
</build>
At this time, the packaged version ht-ui-web.jar
is only 117kb.
ht
There are only relevant jars under BOOT-INF/lib
But since there are no other dependencies, ht-ui-web.jar
it cannot run as scheduled.
java -jar ht-ui-web-1.0.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: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:521)
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/SpringApplication
at com.nerve.huotong.web.WebApplication.main(WebApplication.java:21)
... 8 more
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 9 more
At this point we need to set up LOADER_PATH
as follows
java -Dloader.path="libs/" -jar ht-ui-web.jar
You can see the familiar Spring Boot startup information.
continue to lose weight
As mentioned in the project structure introduction above ht-cdn
, I put all the libraries used in the front end here. Then start a Web Application separately. If other projects need to use static resources, just use them directly.
Another way is to resources/public
throw it directly to libs
the bottom (that is, put it together with the jar package stripped out in the previous step). The structure is as follows:
This is also possible (but be careful not to have the same name as the static resources you wrote in the real project).
Conclusion
After the above slimming down, the Jar package developed in each iteration appears much slimmer.
digression
banner.txt in Spring Boot
Banner is the Easter egg information printed on the console when the spring boot application starts. The default is like this
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.4.3.RELEASE)
If you want to modify this text, just create a new one resources
below banner.txt
. You can customize the banner here: http://patorjk.com/software/taag