SpringBoot package deployment resolution

The SpringBoot project supports two common forms of packaging: JAR packages and WAR packages. By default, Spring Boot projects are created as JAR packages. If the project requires a WAR package, you can modify the configuration to create a WAR package.

In this chapter, we will explain how jar packages and WAR packages work and how they operate.

SpringBoo jars

Spring Boot’s JAR package project is easy to publish, fast, and has a built-in Web container, so Spring Boot makes it the default option. While enjoying the convenience, we also need to know a little bit about how Spring Boot’s JAR package is generated and how to get it up and running. This section analyzes the implementation of Spring Boot from the generation, structure and operation principle of JAR package.

Generation of JAR packages

Spring Boot’s executable JAR package, also known as the FAT JAR, is the JAR that contains all three dependencies. It differs from traditional JAR packages in that it includes a lib directory and an embedded Web container (tomcat is used as an example below).

Jar packages are typically generated by maven plug-ins integrated in the POM.xml file.

Plugins are configured in the BUILD element of the POM file.

<build>
<plugins>
<plugin>
<groupId>org . springframework. boot</groupId>
<artifactId>spring- boot-maven- plugin</ artifactId>
</plugin>
</plugins>
</build>
Copy the code

The spring-boot-Maven-plugin project exists in the spring-boot-tools directory. Spring-boot-maven-plugin has five goals by default: repackage, run, start, stop, and build-info. Repackage is used by default when packaging.

The repackage of spring-boot-Maven-plugin can repackage the software package generated by MVN package as an executable package and rename the software package generated by MVN package to *. Original.

This is why spring-boot-Maven-plugin generates two JAR files in the target directory when maven Clean Package is executed.

Spring-learning-0.0.1 - snapshot.jarCopy the code

Spring-learning-0.0.1 – snapshot.jar. Original: spring-learning-0.01-snapshotjar. Original: spring-learning-0.0.1 – snapshot.jar. The generated new JAR package is the package that contains the business code (a normal JAR package). The spring-learning-0.01-snapshotjar package is a jar jar package launched in Spring Boot. It contains application dependencies and Spring Boot related classes.

The spring-boot-Maven-plugin repackage invokes the RepackageMojo execute method at the code level. The RepackageMojo class provides the ability to repackage existing jar or war package files so that they can be launched using javajar.

The execute method of RepackageMojo is as follows.

@Override public void execute() throws MojoExecut ionException, MojoFailureException if (this. project . getPackaging() . equals("pom")) { getLog() . debug("repackage goal could not be  applied to pom project."); return; if (this.skip) { getLog() . debug("skipping repackaging as per configuration."); return; repackage(); }Copy the code

The execute method checks whether the project is a POM project and whether the project is skipped. If so, the debug log is printed and returned. Otherwise, proceed with the repackage method. The related source code and operations of repackage method in RepackageMojo are analyzed as follows.

Private void rePackage () throws MojoExecutionException {// Jar generated by Maven, Artifact source = getSourceArtifact(); Artifact source = Artifact source (); Artifact source = Artifact source (); Fat jar File target = getTargetFile(); Jar Repackager Repackager = getRepackager(source.getFile ()); Jar Set<Artifact> artifacts = filterDependenc ies(this.project.getartifacts ()) getFilters(getAdditionalFilt ers())); // Convert artifacts to Libraries Libraries Libraries = new ArtifactsLibraries(artifacts, this.requiresunpa k, getLog()); LaunchScript = getLaunchScript(); Fat jar repackager. repackage(target, libraries, launchScript); catch (IOException ex) { throw new MojoExecut ionException(ex. getMessage(), ex); UpdateArtifact (source, target, repackager.getBackupFile ()); }Copy the code

The process for the entire repackage method is commented in the code above. The basic process is as follows: Get the normal JAR package generated by Maven, get the target File object, get the repacker, get the dependent JAR package, get the startup script, Finally, it is repackaged through a repacker into a JAR package that can be executed through java-JAR.

We focus on getting the source code for the method getRepackager.

private Repackager getRepackager(File source) { Repackager repackager = new Repackager(source, this . layoutFactory); repackager . addMainClassTimeoutWarningL istener( new LoggingMainClassTimeoutWarningl istener()); // Set the name of the main class. // repackage will look for the first class that contains the main method and will finally set org.springFramework.boot.loader. JarLauncher repackager. setMainClass(this . mainClass); if (this.layout ! = null) { getLog(). info("Layout: "+ this. layout); // For example, layout returns @org.springFramework.boot.loader.tools.tools.jar repackager.setLayout (this.layout.layout ()); } return repackager; }Copy the code

The getRepackager method basically creates a Repackager object based on the file to be converted (JAR or WAR), And set the start with MainClass is org. Springframework.. The boot loader. JarLauncher, this configuration corresponding to the jar package Manifest. MF MainClass values within the file.

At the same time, if layout is not null, use the layout method provided by the inner enumeration class L ayoutType to get the corresponding repackaged implementation class. Such as against the jar package org. Springframework.. The boot loader. View Layouts. The jar.

The enumerated class LayoutType is defined as follows.

public enum LayoutType {
JAR(new Jar()),WAR(new War()),
ZIP(new Expanded()),
DIR(new Expanded()),
NONE(new None());
}
Copy the code

As you can see from the LayoutType definition, Spring Boot supports several types of archive: JAR type, WAR type, ZIP type, file directory type, and NONE. Obviously, the same implementation class is used to handle ZIP files and DIR files.

The INSIDE of the Layouts class is a quick look at the contents of the processing classes of the JAR type.

Public static class Jar implements RepackagingLayout {public static class Jar implements RepackagingLayout @override public String getLauncherClassName() { return "org. springframework. boot . loader.Jarlauncher"; @override public String getL ibraryDestination(String libraryName, LibraryScope scop return "BOOT - INF/lib/"; / / get to repackage the class file path @ Override public String getRepackagedClassesLocation () {return "BOOT - INF/classes/"; }}Copy the code

The jar file contains the main-class (JarLauncher) boot-INF /lib/ directory and boot-INF /classes/ directory that the JAR package starts. If you look at Expanded and None classes, you’ll see that they inherit from JARS.

Finally, let’s take a quick look at the Repackage method of the Repackager retrieved by the Repackage call in RepackageMojo. The source code of repackage method in Repackager is as follows.

public void repackage(File destination, Libraries libraries, 1 aunch LaunchScript Script) throws IOException {/ / calibration target file F (destination = = null | | destination. The isDirectory ()) throw new illegalArgumentException("Invalid destination"); F (libraries = null) {throw new IllegalArgumentException(" libraries must not be nu1l"); If (this.Layout == null) {this.Layout = getL ayoutFactory().getLayout (this.source); destination = destination. getAbsoluteFile(); File workingSource = this. source; If (alreadyRepackaged() && this.source.equals (destination)) {if (alreadyRepackaged() && this.source.equals (destination)) { If (this.source.equals (destination)) {workingSource = getBackupFile(); workingSource. delete(); renameFile(this. source, workingSource); destination. delete(); Try {try (JarFile jarFileSource = new JarFile(workingSource)) repackage(jarFileSource, destination, libraries, launchScript); } finally { if (! this . backupSource && ! this. source . equals (workingSource)) { deleteFile(workingSource); }}}Copy the code

The core business logic of the above code is as follows.

Verify various parameters (whether files and paths exist).

Backup Files to be repacked end in. Original. If backup files already exist, delete them first.

: Clear the target file before generating it.

Invoke the overloaded repackage method to generate a concrete (JAR package) file and write the MANIFESTMF information.

Finally, determine and perform the workingSource cleanup operation.

To sum up the process in one sentence: When the conditions are met, make a backup of the original JAR package file and generate a new one that can be launched from jar-jar.

We’ll cover the directory structure of the repackaged JAR and the information in the manifest.mf file in the next section.

Jar package structure

In the last section, through the spring – the boot – maven – plugin was born into an executable jar package, the following analysis – the spring jar package – learn – 0.0.1 – the SNAPSHOT. The directory structure of a jar.

In the above structure, the boot-INF /classes directory stores the service code, and the boot-INF /ib directory stores all dependencies except the Java VIRTUAL machine. The org directory contains the relevant class files used by Spring Boot to start jar packages. The meta-INF directory holds the manifest.mf, maven information, and spring Factories files.

The manifest.mf file, which is usually used to define extension or archive packaging related data, is a metadata file in the format of name/value pairs. An executable JAR file is needed to indicate the main class of the program.

Manifest-Version: 1.0
Implementation-Title: spring-learn
Implementation-Version: 0. 0.1-SNAPSHOT
Start-Class: com. secbro2. learn. SpringLearnApplication
Spring - Boot-Classes: B0OT-INF/classes/
Spring-Boot-Lib: B0OT-INF/lib/
Build-Jdk-Spec: 1.8
Spring- Boot -Version: 2.2.1. RELEASE
Created-By: Maven Archiver 3.4.0
Main-Class: org. springframework . boot . loader .Jarlauncher
Copy the code

Manifest. MF file defined in the Main – Class set to org. Springframework.. The boot loader. JarLauncher, that is to say, The jar program starts with the main method of the jarl. auncher class. The JarLauncher class is located in the spring-boot-Loader project, and the class file of the Launcher class is stored in the org directory of the JAR package.

The bow guide Class of a project is defined in the start-class attribute. Note that the start-class attribute is not the Manifest.mf attribute of the Java standard.

Three things to watch ❤️

If you find this article helpful, I’d like to invite you to do three small favors for me:

  1. Like, forward, have your “like and comment”, is the motivation of my creation.

  2. Follow the public account “Java rotten pigskin” and share original knowledge from time to time.

  3. Also look forward to the follow-up article ing🚀

  4. [666] Scan the code to obtain the learning materials package

Article is not original, and all of us feel while reading the article good remember thumb up forward + attention oh ~ this article source: www.toutiao.com/i6895689663…