Slim down the jar package deployed by your SpringBoot project!

187c425919c9b42173d8337c6d02e44e.jpeg

I have written an article about maven plugin before

Detailed explanation of spring-boot-maven-plugin plug-in

1. Demand background

We know that the Spring Boot project can be started through java -jar package name.

So why can the Spring Boot project be started through the above command, but other ordinary projects cannot?

The reason is that when we package through the following command

mvn clean package

The general maven project packaging command will not package the dependent jar packages, so the packages generated in this way are generally very small.

9325d53a30a1239ec0a832536e792a45.jpeg

However, the pom.xml file of a Spring Boot project generally contains the spring-boot-maven-plugin plug-in.

The function of this plug-in is to package all dependent jar packages into it. This file contains all dependencies and resource files.

This will also cause the package to be typed out to be larger.

e08a683c5447f2a9a5d348dd08c4b7f1.jpeg

After packaging, you can start it through java -jar package name, which is really convenient.

But when a system goes online, there will definitely be demand iterations and bug fixes, so repackaging and deployment will be inevitable.

We can imagine a scenario where there is an urgent and fatal bug online. You quickly locate the problem and just change a line of code. When the code is submitted, the build is completed, packaged and delivered to operation and maintenance.

Because the packaged jar is very large, it is always being uploaded…

If you were the boss, you would definitely get angry. You changed a line of code but uploaded a file of hundreds of MB. Isn’t there a way to optimize it?

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 demonstrate how to lose weight.

2. Principles of weight loss

Here is the most basic SpringBoot project. The entire project code is just a SpringBoot startup class, but the packaged jar is more than 20M;

Let’s look at the components of the jar through the decompression command.

tar -zxvf spring-boot-maven-slim-1.0.0.jar

7cb11cf3de712f15001b67806d00cd19.jpeg

We can see that the decompressed package has three modules

Divided into three parts: BOOT-INF, META-INF, org

Open BOOT-INF

b2765e47be9cc35f8549be2d0c051597.jpeg

classes: The compiled code of the current project is placed in classes, and the classes part is very small.

lib: The jar packages we depend on are placed in the lib folder, and the lib part will be very large.

After seeing this structure, how should we lose weight?

Although the project will have many dependencies, once the version iteration becomes stable, the dependencies will basically not change.

If you can put these unchanged dependencies on the server in advance and ignore these dependencies when packaging, then the generated Jar package will be much smaller, which directly improves the release efficiency.

Of course you must have questions about this?

Since these dependencies are ignored during packaging, can it still be started through java -jar package name?

For packages packaged in this way, when starting the project, you need to specify the lib path through -Dloader.path, and it can start normally.

java -Dloader.path=./lib -jar xxx.jar

3. Weight loss example demonstration

1. Dependency split configuration

Just add the following configuration to the project pom.xml file:

<build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
     <executable>true</executable>
     <layout>ZIP</layout>
     <!--Here is the jar that needs to be included.
          Certain modules in the necessary project will change frequently, so their coordinates should be written in
          If not, then nothing means that the dependency is not packaged -->
     <includes>
      <include>
       <groupId>nothing</groupId>
       <artifactId>nothing</artifactId>
      </include>
     </includes>
    </configuration>
   </plugin>

   <!--Copy dependencies to the lib directory outside the jar-->
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
     <execution>
      <id>copy</id>
      <phase>package</phase>
      <goals>
       <goal>copy-dependencies</goal>
      </goals>
      <configuration>
       <!--Specified dependency path-->
       <outputDirectory>
        ${project.build.directory}/lib
       </outputDirectory>
      </configuration>
     </execution>
    </executions>
   </plugin>
  </plugins>
 </build>

Pack again

mvn clean package

c80445d64e8be38854bca3e53ec25956.jpeg

It was found that there is an additional lib folder in the target directory, which contains all dependent jars.

4050025e732497e833ee432ad6cc8e52.jpeg

The jar related to my own business is only 168kb, which is more than 100 times smaller than the previous 20.2M;

For packages packaged in this way, when starting the project, you need to specify the lib path through -Dloader.path:

java -Dloader.path=./lib -jar spring-boot-maven-slim-1.0.0.jar

1be749e5936da41b3de07bb3a9e84c36.jpeg

Although packaged in this way, the size of the three-party dependencies has not changed at all, but the big difference is that our own Business package and Dependency package are separated;

Without changing the dependencies, you only need to upload the lib directory to the server for the first time. For subsequent business adjustments and bug fixes, without adjusting the dependencies, you only need to upload the updated file. A small business package is enough;

2. How to deal with the dependencies of other projects?

When we develop projects, in addition to citing third-party dependencies, we also rely on other modules of our own company.

for example

2d937a67484939a5f786a5c676bd3370.jpeg

This kind of project that relies on other projects of its own will also change frequently, so it is not suitable to use external lib, otherwise it will need to be uploaded and updated frequently.

How to do it?

It’s actually very simple. Just fill in the plugin you need to enter into the jar above.

<plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 <configuration>
  <executable>true</executable>
  <layout>ZIP</layout>
  <!--Here is the jar that needs to be included, if not, then nothing -->
   <includes>
    <include>
     <groupId>com.jincou</groupId>
     <artifactId>xiaoxiao-util</artifactId>
    </include>
   </includes>
 </configuration>
</plugin>

In this way, only all added dependencies in include will still be included in the current business package.

4. Summary

With slim deployment, your business package is indeed smaller, making it easier to update each iteration without having to upload a large jar package every time, thus saving deployment time.

However, this method also has a drawback, which is that it increases the management cost of the Jar package. Multiple people coordinate development. When building, you need to pay special attention to whether someone updates the dependencies.

Please click three links: like, retweet, and watch.

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 138475 people are learning the system