-Create a Gradle and Maven project with Spring Initializr and examine the contents of the generated WAR file.
Remove the test code etc. from the project created by Spring Initializr to make the following file structure.
Gradle
├── build.gradle
├── settings.gradle
└── src
└── main
├── java
│ └── com
│ └── example
│ ├── MyappApplication.java
│ └── ServletInitializer.java
└── resources
├── application.properties
├── static
└── templates
Maven
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── example
│ ├── MyappApplication.java
│ └── ServletInitializer.java
└── resources
├── application.properties
├── static
└── templates
The contents are the same except for the configuration file.
$ diff -r gradle/myapp maven/myapp
Only in gradle/myapp: build.gradle
Only in maven/myapp: pom.xml
Only in gradle/myapp: settings.gradle
Add the external library Apache PDFBox. This is to find out how external libraries other than Spring are stored in the WAR file.
Gradle (build.gradle)
plugins {
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
id 'war'
}
group = 'com.example'
version = '0.0.1'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
// https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox
implementation 'org.apache.pdfbox:pdfbox:2.0.19'
implementation 'org.springframework.boot:spring-boot-starter-web'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
}
Maven (pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>myapp</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<name>myapp</name>
<description>MyApp project</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.19</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Gradle
Uses Gradle 6.3.
$ gradle build
$ unzip build/libs/myapp-0.0.1.war -d dest
Maven
Uses Apache Maven 3.6.3.
$ mvn package
$ unzip target/myapp-0.0.1.war -d dest
--The class file created by compiling the source code goes into WEB-INF / classes --Spring related JAR files go into WEB-INF / lib --The JAR file of the external library goes to WEB-INF / lib (Apache PDFBox pdfbox-2.0.19.jar is in WEB-INF / lib) --Files that are considered unnecessary as WAR such as tomcat-embed-core-9.0.33.jar are in WEB-INF / lib-provided. --Spring Boot Loader class files go into org / springframework / boot / loader
Spring Boot executable Jar format -Document
Dependencies must be placed in a nested WEB-INF / lib directory. Dependencies that are required when running the built-in but are not needed when deploying to a traditional web container should be placed in WEB-INF / lib-provided.
Spring Boot executable Jar format -Document
Java does not provide a standard way to load nested jar files (that is, the jar files contained within the jar). This can be a problem if you need to distribute a self-contained application that can be run without deploying from the command line.
To solve this problem, many developers use "shaded" jar files. The shaded jar packages all the classes from all the jars into a single "uber jar". The problem with shaded jar files is that it's hard to see which libraries are actually included in your application. Also, problems can occur if multiple jars use the same filename (but with different content). Spring Boot takes a different approach and can actually nest jars directly.
Gradle
$ tree dest
dest
├── META-INF
│ └── MANIFEST.MF
├── WEB-INF
│ ├── classes
│ │ ├── application.properties
│ │ ├── com
│ │ │ └── example
│ │ │ ├── MyappApplication.class
│ │ │ └── ServletInitializer.class
│ │ ├── static
│ │ └── templates
│ ├── lib
│ │ ├── classmate-1.5.1.jar
│ │ ├── commons-logging-1.2.jar
│ │ ├── fontbox-2.0.19.jar
│ │ ├── hibernate-validator-6.0.18.Final.jar
│ │ ├── jackson-annotations-2.10.3.jar
│ │ ├── jackson-core-2.10.3.jar
│ │ ├── jackson-databind-2.10.3.jar
│ │ ├── jackson-datatype-jdk8-2.10.3.jar
│ │ ├── jackson-datatype-jsr310-2.10.3.jar
│ │ ├── jackson-module-parameter-names-2.10.3.jar
│ │ ├── jakarta.validation-api-2.0.2.jar
│ │ ├── jboss-logging-3.4.1.Final.jar
│ │ ├── jul-to-slf4j-1.7.30.jar
│ │ ├── log4j-api-2.12.1.jar
│ │ ├── log4j-to-slf4j-2.12.1.jar
│ │ ├── logback-classic-1.2.3.jar
│ │ ├── logback-core-1.2.3.jar
│ │ ├── pdfbox-2.0.19.jar
│ │ ├── slf4j-api-1.7.30.jar
│ │ ├── snakeyaml-1.25.jar
│ │ ├── spring-aop-5.2.5.RELEASE.jar
│ │ ├── spring-beans-5.2.5.RELEASE.jar
│ │ ├── spring-boot-2.2.6.RELEASE.jar
│ │ ├── spring-boot-autoconfigure-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-json-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-logging-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-validation-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-web-2.2.6.RELEASE.jar
│ │ ├── spring-context-5.2.5.RELEASE.jar
│ │ ├── spring-core-5.2.5.RELEASE.jar
│ │ ├── spring-expression-5.2.5.RELEASE.jar
│ │ ├── spring-jcl-5.2.5.RELEASE.jar
│ │ ├── spring-web-5.2.5.RELEASE.jar
│ │ └── spring-webmvc-5.2.5.RELEASE.jar
│ └── lib-provided
│ ├── jakarta.annotation-api-1.3.5.jar
│ ├── spring-boot-starter-tomcat-2.2.6.RELEASE.jar
│ ├── tomcat-embed-core-9.0.33.jar
│ ├── tomcat-embed-el-9.0.33.jar
│ └── tomcat-embed-websocket-9.0.33.jar
└── org
└── springframework
└── boot
└── loader
├── ExecutableArchiveLauncher.class
├── JarLauncher.class
├── LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
├── LaunchedURLClassLoader.class
├── Launcher.class
├── MainMethodRunner.class
├── PropertiesLauncher$1.class
├── PropertiesLauncher$ArchiveEntryFilter.class
├── PropertiesLauncher$PrefixMatchingArchiveFilter.class
├── PropertiesLauncher.class
├── WarLauncher.class
├── archive
│ ├── Archive$Entry.class
│ ├── Archive$EntryFilter.class
│ ├── Archive.class
│ ├── ExplodedArchive$1.class
│ ├── ExplodedArchive$FileEntry.class
│ ├── ExplodedArchive$FileEntryIterator$EntryComparator.class
│ ├── ExplodedArchive$FileEntryIterator.class
│ ├── ExplodedArchive.class
│ ├── JarFileArchive$EntryIterator.class
│ ├── JarFileArchive$JarFileEntry.class
│ └── JarFileArchive.class
├── data
│ ├── RandomAccessData.class
│ ├── RandomAccessDataFile$1.class
│ ├── RandomAccessDataFile$DataInputStream.class
│ ├── RandomAccessDataFile$FileAccess.class
│ └── RandomAccessDataFile.class
├── jar
│ ├── AsciiBytes.class
│ ├── Bytes.class
│ ├── CentralDirectoryEndRecord$1.class
│ ├── CentralDirectoryEndRecord$Zip64End.class
│ ├── CentralDirectoryEndRecord$Zip64Locator.class
│ ├── CentralDirectoryEndRecord.class
│ ├── CentralDirectoryFileHeader.class
│ ├── CentralDirectoryParser.class
│ ├── CentralDirectoryVisitor.class
│ ├── FileHeader.class
│ ├── Handler.class
│ ├── JarEntry.class
│ ├── JarEntryFilter.class
│ ├── JarFile$1.class
│ ├── JarFile$2.class
│ ├── JarFile$JarFileType.class
│ ├── JarFile.class
│ ├── JarFileEntries$1.class
│ ├── JarFileEntries$EntryIterator.class
│ ├── JarFileEntries.class
│ ├── JarURLConnection$1.class
│ ├── JarURLConnection$2.class
│ ├── JarURLConnection$CloseAction.class
│ ├── JarURLConnection$JarEntryName.class
│ ├── JarURLConnection.class
│ ├── StringSequence.class
│ └── ZipInflaterInputStream.class
└── util
└── SystemPropertyUtils.class
17 directories, 99 files
Maven
$ tree dest
dest
├── META-INF
│ ├── MANIFEST.MF
│ └── maven
│ └── com.example
│ └── myapp
│ ├── pom.properties
│ └── pom.xml
├── WEB-INF
│ ├── classes
│ │ ├── application.properties
│ │ └── com
│ │ └── example
│ │ ├── MyappApplication.class
│ │ └── ServletInitializer.class
│ ├── lib
│ │ ├── classmate-1.5.1.jar
│ │ ├── commons-logging-1.2.jar
│ │ ├── fontbox-2.0.19.jar
│ │ ├── hibernate-validator-6.0.18.Final.jar
│ │ ├── jackson-annotations-2.10.3.jar
│ │ ├── jackson-core-2.10.3.jar
│ │ ├── jackson-databind-2.10.3.jar
│ │ ├── jackson-datatype-jdk8-2.10.3.jar
│ │ ├── jackson-datatype-jsr310-2.10.3.jar
│ │ ├── jackson-module-parameter-names-2.10.3.jar
│ │ ├── jakarta.annotation-api-1.3.5.jar
│ │ ├── jakarta.validation-api-2.0.2.jar
│ │ ├── jboss-logging-3.4.1.Final.jar
│ │ ├── jul-to-slf4j-1.7.30.jar
│ │ ├── log4j-api-2.12.1.jar
│ │ ├── log4j-to-slf4j-2.12.1.jar
│ │ ├── logback-classic-1.2.3.jar
│ │ ├── logback-core-1.2.3.jar
│ │ ├── pdfbox-2.0.19.jar
│ │ ├── slf4j-api-1.7.30.jar
│ │ ├── snakeyaml-1.25.jar
│ │ ├── spring-aop-5.2.5.RELEASE.jar
│ │ ├── spring-beans-5.2.5.RELEASE.jar
│ │ ├── spring-boot-2.2.6.RELEASE.jar
│ │ ├── spring-boot-autoconfigure-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-json-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-logging-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-validation-2.2.6.RELEASE.jar
│ │ ├── spring-boot-starter-web-2.2.6.RELEASE.jar
│ │ ├── spring-context-5.2.5.RELEASE.jar
│ │ ├── spring-core-5.2.5.RELEASE.jar
│ │ ├── spring-expression-5.2.5.RELEASE.jar
│ │ ├── spring-jcl-5.2.5.RELEASE.jar
│ │ ├── spring-web-5.2.5.RELEASE.jar
│ │ └── spring-webmvc-5.2.5.RELEASE.jar
│ └── lib-provided
│ ├── spring-boot-starter-tomcat-2.2.6.RELEASE.jar
│ ├── tomcat-embed-core-9.0.33.jar
│ ├── tomcat-embed-el-9.0.33.jar
│ └── tomcat-embed-websocket-9.0.33.jar
└── org
└── springframework
└── boot
└── loader
├── ExecutableArchiveLauncher.class
├── JarLauncher.class
├── LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
├── LaunchedURLClassLoader.class
├── Launcher.class
├── MainMethodRunner.class
├── PropertiesLauncher$1.class
├── PropertiesLauncher$ArchiveEntryFilter.class
├── PropertiesLauncher$PrefixMatchingArchiveFilter.class
├── PropertiesLauncher.class
├── WarLauncher.class
├── archive
│ ├── Archive$Entry.class
│ ├── Archive$EntryFilter.class
│ ├── Archive.class
│ ├── ExplodedArchive$1.class
│ ├── ExplodedArchive$FileEntry.class
│ ├── ExplodedArchive$FileEntryIterator$EntryComparator.class
│ ├── ExplodedArchive$FileEntryIterator.class
│ ├── ExplodedArchive.class
│ ├── JarFileArchive$EntryIterator.class
│ ├── JarFileArchive$JarFileEntry.class
│ └── JarFileArchive.class
├── data
│ ├── RandomAccessData.class
│ ├── RandomAccessDataFile$1.class
│ ├── RandomAccessDataFile$DataInputStream.class
│ ├── RandomAccessDataFile$FileAccess.class
│ └── RandomAccessDataFile.class
├── jar
│ ├── AsciiBytes.class
│ ├── Bytes.class
│ ├── CentralDirectoryEndRecord$1.class
│ ├── CentralDirectoryEndRecord$Zip64End.class
│ ├── CentralDirectoryEndRecord$Zip64Locator.class
│ ├── CentralDirectoryEndRecord.class
│ ├── CentralDirectoryFileHeader.class
│ ├── CentralDirectoryParser.class
│ ├── CentralDirectoryVisitor.class
│ ├── FileHeader.class
│ ├── Handler.class
│ ├── JarEntry.class
│ ├── JarEntryFilter.class
│ ├── JarFile$1.class
│ ├── JarFile$2.class
│ ├── JarFile$JarFileType.class
│ ├── JarFile.class
│ ├── JarFileEntries$1.class
│ ├── JarFileEntries$EntryIterator.class
│ ├── JarFileEntries.class
│ ├── JarURLConnection$1.class
│ ├── JarURLConnection$2.class
│ ├── JarURLConnection$CloseAction.class
│ ├── JarURLConnection$JarEntryName.class
│ ├── JarURLConnection.class
│ ├── StringSequence.class
│ └── ZipInflaterInputStream.class
└── util
└── SystemPropertyUtils.class
18 directories, 101 files
It doesn't change much.
$ diff -r gradle/myapp/dest maven/myapp/dest
diff -r gradle/myapp/dest/META-INF/MANIFEST.MF maven/myapp/dest/META-INF/MANIFEST.MF
1a2,5
> Created-By: Maven Archiver 3.4.0
> Build-Jdk-Spec: 11
> Implementation-Title: myapp
> Implementation-Version: 0.0.1
Only in maven/myapp/dest/META-INF: maven
Only in gradle/myapp/dest/WEB-INF/classes: static
Only in gradle/myapp/dest/WEB-INF/classes: templates
Only in maven/myapp/dest/WEB-INF/lib: jakarta.annotation-api-1.3.5.jar
Only in gradle/myapp/dest/WEB-INF/lib-provided: jakarta.annotation-api-1.3.5.jar
Recommended Posts