image.png
创建独立的Spring应用作为Spring Boot的首要特性。

  • 为什么需要独立的应用?
    Spring Boot应用无需像传统的Java EE那样将应用打包成WAR或者EAR包,并部署到Java EE容器中。
    Spring Boot应用采用嵌入式容器,独立于外部容器,对应用生命周期拥有完全自主的控制
  • 为什么为Spring应用而非Spring Boot应用
    当Spring Boot的嵌入式容器成为应用的一部分,从本质上来说,属于Spring应用上下文中的组建Beans,由自动装配特性组装成Spring Bean定义,随Spring应用上下文启动而注册并初始化。启动上下文的核心组件是Spring Boot核心API SpringApplication

创建Spring Boot项目

CMD命令行模式创建

图形化界面创建Spring Boot应用

Spring官方提供的在线创建 https://start.spring.io/
image.png

IDE集成创建

例如idea
image.png

Spring Boot模版目录

image.png
简单选择了几个常用的框架组建后如上图,其包含如上图结构

  • .gitignore文件
    引入该文件的目的是因为Git作为大多数代码版本控制,定义了最常见的文件或目录的版本控制忽略文件
  • Maven Wrapper文件
    image.png
    包含.mvn目录、执行脚本mvnw和mvnw.cmd
    1.Maven Wrapper是一种简单的Maven构建方式,运行环境不需要提前安装Maven二进制文件
    2.jar由脚本引导,用于从Maven官方下载Maven二进制文件
    3.properties定义文件下载URL
    4.mvnw、mvnw.cmd引导jar的unix-like的shell脚本和win脚本
  • Spring Boot应用属性配置文件-application.properties
    Spring Boot默认的应用外部配置文件
  • Spring Boot应用测试文件
    image.png
    提供Spring Boot集成测试的基本模式

创建Spring Boot应用可执行JAR

构建可执行JAR的前提需要在pom中添加spring-boot-maven-plugin
如果通过 https://start.spring.io/ 构建项目则默认添加该插件
image.png
且默认继承自spring-boot-starter-parent 所以不需要指定Maven依赖和插件的版本

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

运行Spring Boot应用

java --help
用法: java [-options] class [args...]
           (执行类)
   或  java [-options] -jar jarfile [args...]
           (执行 jar 文件)

执行Spring Boot应用可执行JAR

  • java -jar
  • mvn spring-boot:run
    二者命令基本无差异,运行速度也不熟影响,前者多用于生产环境运行方式,后者为开发阶段运行方式

Spring Boot应用可执行Jar资源结构

image.png
***.jar.original属于原始Maven打包JAR文件
***.jar是被spring-boot-mavven-plugin Mven插件加功引入相关第三方依赖资源后的JAR文件
Spring Boot打包后的JAR文件在模仿Java EE的WAR文件结构

FAT JAR 和WAR执行模块——spring-boot-loader

Java官方规定 java -jar 命令引导的具体启动类必须配置在MANIFEST.MF资源的Main-Class属性中,且放置在/META-INF/目录下

Manifest-Version: 1.0
Implementation-Title: ***
Implementation-Version: ***
Start-Class: ****
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.1.7.RELEASE
Created-By: Maven Archiver 3.4.0
Main-Class: org.springframework.boot.loader.PropertiesLauncher

其main class为org.springframework.boot.loader.PropertiesLauncher。

https://docs.spring.io/spring-boot/docs/2.5.0-SNAPSHOT/reference/html/appendix-executable-jar-format.html#executable-jar-property-launcher-features
image.png
有三种启动器
org.springframework.boot.loader.JarLauncher
org.springframework.boot.loader.WarLauncher
org.springframework.boot.loader.PropertiesLauncher
分别启动JAR包,WAR包和设置外部属性启动

可执行JAR文件启动器:JarLauncher

org.springframework.boot.loader.JarLauncher并非项目中的文件,由插件spring-boot-maven-plugin追加进去的。
image.png
导入依赖坐标,或者解压打包好的Spring Boot项目jar可以查看到相关信息
image.png
可以通过解压jar包后,直接java运行该类也可以启动项目

JarLauncher的实现原理

image.png

public class JarLauncher extends ExecutableArchiveLauncher {
    static final String BOOT_INF_CLASSES = "BOOT-INF/classes/";
    static final String BOOT_INF_LIB = "BOOT-INF/lib/";

    public JarLauncher() {
    }

    protected JarLauncher(Archive archive) {
        super(archive);
    }

    protected boolean isNestedArchive(Entry entry) {
        return entry.isDirectory() ? entry.getName().equals("BOOT-INF/classes/") : entry.getName().startsWith("BOOT-INF/lib/");
    }

    public static void main(String[] args) throws Exception {
        (new JarLauncher()).launch(args);
    }
}

image.png
image.png
image.png
mainClass类名字来自/META-INF/MANIFEST.MF的Start-Class属性,且子类并未覆盖该方法。无论JAR或者WAR读取的Spring Boot启动类均来自此属性

可执行WAR文件启动器:WarLauncher

Warlauncher与JarLauncher的差异较小,主要区别在于项目文件和Jar Class Path路径不同

public class WarLauncher extends ExecutableArchiveLauncher {
    private static final String WEB_INF = "WEB-INF/";
    private static final String WEB_INF_CLASSES = "WEB-INF/classes/";
    private static final String WEB_INF_LIB = "WEB-INF/lib/";
    private static final String WEB_INF_LIB_PROVIDED = "WEB-INF/lib-provided/";

    public WarLauncher() {
    }

    protected WarLauncher(Archive archive) {
        super(archive);
    }

    public boolean isNestedArchive(Entry entry) {
        if (entry.isDirectory()) {
            return entry.getName().equals("WEB-INF/classes/");
        } else {
            return entry.getName().startsWith("WEB-INF/lib/") || entry.getName().startsWith("WEB-INF/lib-provided/");
        }
    }

    public static void main(String[] args) throws Exception {
        (new WarLauncher()).launch(args);
    }
}

由于打包后的文件目录存放不同。
传统的WEB-INF/lib-provided的JAR将被Servlet容器忽略,如Servlet API。
打包后的WAR文件能够在Servlet容器中兼容运行。

打包WAR文件是一种兼容措施,技能被WarLauncher启动,又能兼容Servlet容器环境。WarLauncher与JarLauncher并无被指差别。Spring Boot应用使用非传统Web部署时,尽可能使用JAR归档方式。
JAR和WAR归档应用均为Spring Boot独立应用


这个家伙很懒,啥也没有留下😋