亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java?-jar命令及SpringBoot通過java?-jav啟動(dòng)項(xiàng)目的過程

 更新時(shí)間:2023年05月15日 09:56:49   作者:張某某啊哈  
本篇文章將為大家講述關(guān)于 SpringBoot 項(xiàng)目工程完成后,是如何通過 java-jar 命令來啟動(dòng)的,以及介紹 java-jar 命令的詳細(xì)內(nèi)容,對(duì)SpringBoot java?-jav啟動(dòng)過程感興趣的朋友跟隨小編一起看看吧

本篇文章將為大家講述關(guān)于 SpringBoot 項(xiàng)目工程完成后,是如何通過 java-jar 命令來啟動(dòng)的,以及介紹 java-jar 命令的詳細(xì)內(nèi)容。希望本篇文章能夠幫助到大家的學(xué)習(xí)!

Pre

大家開發(fā)的基于Spring Boot 的應(yīng)用 ,jar形式, 發(fā)布的時(shí)候,絕大部分都是使用java -jar 啟動(dòng)。 得益于Spring Boot 的封裝 , 再也不用操心搭建tomcat等相關(guān)web容器le , 一切變得非常美好, 那SpringBoot是怎么做到的呢?

引導(dǎo)

新建工程 打包 啟動(dòng)

我們新創(chuàng)建一個(gè)Spring Boot的工程

其中打包的配置為

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

先打包一下

查看target目錄

然后啟動(dòng)

java -jar 干啥的

我們先看看 java -jar 干了啥 ?

在oracle官網(wǎng)找到了該命令的描述:

If the -jar option is specified, its argument is the name of the JAR file containing class and resource files for the application. The startup class must be indicated by the Main-Class manifest header in its source code.

使用-jar參數(shù)時(shí),后面的參數(shù)是的jar 【spring-0.0.1-SNAPSHOT.jar】,該jar文件中包含的是class和資源文件; 在manifest文件中有Main-Class的定義;Main-Class的源碼中指定了整個(gè)應(yīng)用的啟動(dòng)類;

簡(jiǎn)單來說: java -jar會(huì)去找jar中的manifest文件,去找到Main-Class對(duì)應(yīng)的真正的啟動(dòng)類;

那看看去吧

咦 ,這個(gè)Main-Class 是Spring Boot 的。

我們還看到有個(gè)Start Class

官方文檔中,只提到過Main-Class ,并沒有提到Start-Class;
Start-Class的值是com.artisan.spring.Application,這是我們的java代碼中的唯一類,包含main方法, 是能夠真正的應(yīng)用啟動(dòng)類

所以問題就來了:理論上看,執(zhí)行java -jar命令時(shí)JarLauncher類會(huì)被執(zhí)行,但實(shí)際上是com.artisan.spring.Application被執(zhí)行了,這其中發(fā)生了什么呢?why?

打包插件

事實(shí)上,Java沒有提供任何標(biāo)準(zhǔn)的方式來加載嵌套的jar文件 (jar中包含jar ,即Spring Boot 中的fat jar)

Spring Boot 默認(rèn)的打包插件如下:

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

執(zhí)行maven clean package之后,會(huì)生成兩個(gè)文件,剛才我們也看到了

spring-boot-maven-plugin簡(jiǎn)介

spring-boot-maven-plugin項(xiàng)目存在于spring-boot-tools目錄中。

spring-boot-maven-plugin默認(rèn)有5個(gè)goals:repackage、run、start、stop、build-info。在打包的時(shí)候默認(rèn)使用的是repackage。

spring-boot-maven-plugin的repackage能夠?qū)vn package生成的軟件包,再次打包為可執(zhí)行的軟件包,并將mvn package生成的軟件包重命名為.original*

spring-boot-maven-plugin的repackage在代碼層面調(diào)用了RepackageMojoexecute方法,而在該方法中又調(diào)用了repackage方法。

private void repackage() throws MojoExecutionException {
   // maven生成的jar,最終的命名將加上.original后綴
   Artifact source = getSourceArtifact();
   // 最終為可執(zhí)行jar,即fat jar
   File target = getTargetFile();
   // 獲取重新打包器,將maven生成的jar重新打包成可執(zhí)行jar
   Repackager repackager = getRepackager(source.getFile());
   // 查找并過濾項(xiàng)目運(yùn)行時(shí)依賴的jar
   Set<Artifact> artifacts = filterDependencies(this.project.getArtifacts(),
         getFilters(getAdditionalFilters()));
   // 將artifacts轉(zhuǎn)換成libraries
   Libraries libraries = new ArtifactsLibraries(artifacts, this.requiresUnpack,
         getLog());
   try {
      // 獲得Spring Boot啟動(dòng)腳本
      LaunchScript launchScript = getLaunchScript();
      // 執(zhí)行重新打包,生成fat jar
      repackager.repackage(target, libraries, launchScript);
   }catch (IOException ex) {
      throw new MojoExecutionException(ex.getMessage(), ex);
   }
   // 將maven生成的jar更新成.original文件
   updateArtifact(source, target, repackager.getBackupFile());
}

執(zhí)行以上命令之后,便生成了打包結(jié)果對(duì)應(yīng)的兩個(gè)文件。

包結(jié)構(gòu)

下面針對(duì)文件的內(nèi)容和結(jié)構(gòu)進(jìn)行一探究竟。

spring-0.0.1-SNAPSHOT.jar
├── META-INF
│   └── maven(主要是pom文件)
│   └── MANIFEST.MF
├── BOOT-INF
│   ├── classes
│   │   └── 應(yīng)用程序類
│   └── lib
│       └── 第三方依賴jar
└── org
    └── springframework
        └── boot
            └── loader
                └── springboot啟動(dòng)程序

META-INF內(nèi)容

Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Implementation-Title: spring
Implementation-Version: 0.0.1-SNAPSHOT
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Start-Class: com.artisan.spring.Application
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.4.1
Created-By: Maven Jar Plugin 3.2.0
Main-Class: org.springframework.boot.loader.JarLauncher

Main-Class:org.springframework.boot.loader.JarLauncher ,這個(gè)是jar啟動(dòng)的Main函數(shù)Start-Class: com.artisan.spring.Application,這個(gè)是我們應(yīng)用自己的Main函數(shù)

Archive的概念

在繼續(xù)了解底層概念和原理之前,我們先來了解一下Archive的概念:

  • archive即歸檔文件,這個(gè)概念在linux下比較常見
  • 通常就是一個(gè)tar/zip格式的壓縮包
  • jar是zip格式

SpringBoot抽象了Archive的概念,一個(gè)Archive可以是jar(JarFileArchive),可以是一個(gè)文件目錄(ExplodedArchive),可以抽象為統(tǒng)一訪問資源的邏輯層

關(guān)于Spring Boot中Archive的源碼如下:

public interface Archive extends Iterable<Archive.Entry> {
    // 獲取該歸檔的url
    URL getUrl() throws MalformedURLException;
    // 獲取jar!/META-INF/MANIFEST.MF或[ArchiveDir]/META-INF/MANIFEST.MF
    Manifest getManifest() throws IOException;
    // 獲取jar!/BOOT-INF/lib/*.jar或[ArchiveDir]/BOOT-INF/lib/*.jar
    List<Archive> getNestedArchives(EntryFilter filter) throws IOException;
}

SpringBoot定義了一個(gè)接口用于描述資源,也就是org.springframework.boot.loader.archive.Archive。

該接口有兩個(gè)實(shí)現(xiàn),分別是

  • org.springframework.boot.loader.archive.ExplodedArchive
  • org.springframework.boot.loader.archive.JarFileArchive。

前者用于在文件夾目錄下尋找資源,后者用于在jar包環(huán)境下尋找資源。而在SpringBoot打包的fatJar中,則是使用后者JarFileArchive

JarFile

JarFile:對(duì)jar包的封裝,每個(gè)JarFileArchive都會(huì)對(duì)應(yīng)一個(gè)JarFile。

JarFile被構(gòu)造的時(shí)候會(huì)解析內(nèi)部結(jié)構(gòu),去獲取jar包里的各個(gè)文件或文件夾,這些文件或文件夾會(huì)被封裝到Entry中,也存儲(chǔ)在JarFileArchive中。如果Entry是個(gè)jar,會(huì)解析成JarFileArchive。

比如一個(gè)JarFileArchive對(duì)應(yīng)的URL為:

jar:file:/Users/format/Develop/gitrepository/springboot-analysis/springboot-executable-jar/target/executable-jar-1.0-SNAPSHOT.jar!/

它對(duì)應(yīng)的JarFile為:

/Users/format/Develop/gitrepository/springboot-analysis/springboot-executable-jar/target/executable-jar-1.0-SNAPSHOT.jar

這個(gè)JarFile有很多Entry,比如:

META-INF/
META-INF/MANIFEST.MF
spring/
spring/study/
....
spring/study/executablejar/ExecutableJarApplication.class
lib/spring-boot-starter-1.3.5.RELEASE.jar
lib/spring-boot-1.3.5.RELEASE.jar
...

JarFileArchive內(nèi)部的一些依賴jar對(duì)應(yīng)的URL(SpringBoot使用org.springframework.boot.loader.jar.Handler處理器來處理這些URL):

jar:file:/Users/Format/Develop/gitrepository/springboot-analysis/springboot-executable-jar/target/executable-jar-1.0-SNAPSHOT.jar!/lib/spring-boot-starter-web-1.3.5.RELEASE.jar!/
jar:file:/Users/Format/Develop/gitrepository/springboot-analysis/springboot-executable-jar/target/executable-jar-1.0-SNAPSHOT.jar!/lib/spring-boot-loader-1.3.5.RELEASE.jar!/org/springframework/boot/loader/JarLauncher.class

我們看到如果有jar包中包含jar,或者jar包中包含jar包里面的class文件,那么會(huì)使用 !/ 分隔開,這種方式只有org.springframework.boot.loader.jar.Handler能處理,它是SpringBoot內(nèi)部擴(kuò)展出來的一種URL協(xié)議。

JarLauncher工作流程

從MANIFEST.MF可以看到Main函數(shù)是JarLauncher,下面來分析它的工作流程。JarLauncher類的繼承結(jié)構(gòu)是:

class JarLauncher extends ExecutableArchiveLauncher
class ExecutableArchiveLauncher extends Launcher

Launcher for JAR based archives. This launcher assumes that dependency jars are included inside a /BOOT-INF/lib directory and that application classes are included inside a /BOOT-INF/classes directory.

什么意思呢?

按照定義,JarLauncher可以加載內(nèi)部/BOOT-INF/lib下的jar及/BOOT-INF/classes下的應(yīng)用class。

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

其主入口新建了JarLauncher并調(diào)用父類Launcher中的launch方法啟動(dòng)程序。在創(chuàng)建JarLauncher時(shí),父類ExecutableArchiveLauncher找到自己所在的jar,并創(chuàng)建archive。

JarLauncher繼承于org.springframework.boot.loader.ExecutableArchiveLauncher。該類的無參構(gòu)造方法最主要的功能就是構(gòu)建了當(dāng)前main方法所在的FatJar的JarFileArchive對(duì)象。

下面來看launch方法。該方法主要是做了2個(gè)事情:

(1)以FatJar為file作為入?yún)?,?gòu)造JarFileArchive對(duì)象。獲取其中所有的資源目標(biāo),取得其Url,將這些URL作為參數(shù),構(gòu)建了一個(gè)URLClassLoader。

(2)以第一步構(gòu)建的ClassLoader加載MANIFEST.MF文件中Start-Class指向的業(yè)務(wù)類,并且執(zhí)行靜態(tài)方法main。進(jìn)而啟動(dòng)整個(gè)程序。

public abstract class ExecutableArchiveLauncher extends Launcher {
    private final Archive archive;
    public ExecutableArchiveLauncher() {
        try {
            // 找到自己所在的jar,并創(chuàng)建Archive
            this.archive = createArchive();
        }
        catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }
}
public abstract class Launcher {
    protected final Archive createArchive() throws Exception {
        ProtectionDomain protectionDomain = getClass().getProtectionDomain();
        CodeSource codeSource = protectionDomain.getCodeSource();
        URI location = (codeSource == null ? null : codeSource.getLocation().toURI());
        String path = (location == null ? null : location.getSchemeSpecificPart());
        if (path == null) {
            throw new IllegalStateException("Unable to determine code source archive");
        }
        File root = new File(path);
        if (!root.exists()) {
            throw new IllegalStateException(
                    "Unable to determine code source archive from " + root);
        }
        return (root.isDirectory() ? new ExplodedArchive(root)
                : new JarFileArchive(root));
    }
}

在Launcher的launch方法中,通過以上archive的getNestedArchives方法找到/BOOT-INF/lib下所有jar及/BOOT-INF/classes目錄所對(duì)應(yīng)的archive,通過這些archives的url生成LaunchedURLClassLoader,并將其設(shè)置為線程上下文類加載器,啟動(dòng)應(yīng)用。

至此,才執(zhí)行我們應(yīng)用程序主入口類的main方法,所有應(yīng)用程序類文件均可通過/BOOT-INF/classes加載,所有依賴的第三方j(luò)ar均可通過/BOOT-INF/lib加載。

小結(jié)

  • JarLauncher通過加載BOOT-INF/classes目錄及BOOT-INF/lib目錄下jar文件,實(shí)現(xiàn)了fat jar的啟動(dòng)。
  • SpringBoot通過擴(kuò)展JarFile、JarURLConnection及URLStreamHandler,實(shí)現(xiàn)了jar in jar中資源的加載。
  • SpringBoot通過擴(kuò)展URLClassLoader–LauncherURLClassLoader,實(shí)現(xiàn)了jar in jar中class文件的加載。
  • WarLauncher通過加載WEB-INF/classes目錄及WEB-INF/lib和WEB-INF/lib-provided目錄下的jar文件,實(shí)現(xiàn)了war文件的直接啟動(dòng)及web容器中的啟動(dòng)。

通過spring-boot-plugin 生成了MANIFEST.MF , main-class 指定運(yùn)行java -jar的主程序把依賴的jar文件 打包在fat jar.

以上就是關(guān)于 java -jar命令的詳細(xì)內(nèi)容以及 SpringBoot 如何使用 java -jar命令來啟動(dòng)項(xiàng)目的具體過程。

到此這篇關(guān)于java -jar命令及SpringBoot通過java -jav啟動(dòng)的過程的文章就介紹到這了,更多相關(guān)SpringBoot java -jav啟動(dòng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解HTTP請(qǐng)求與響應(yīng)基礎(chǔ)及實(shí)例

    詳解HTTP請(qǐng)求與響應(yīng)基礎(chǔ)及實(shí)例

    這篇文章主要介紹了詳解HTTP請(qǐng)求與響應(yīng)基礎(chǔ)及實(shí)例的相關(guān)資料,這里對(duì)http的請(qǐng)求和響應(yīng)進(jìn)行詳細(xì)分析并附有實(shí)現(xiàn)實(shí)例,需要的朋友可以參考下
    2017-07-07
  • 在SpringBoot中使用HATEOAS的方法

    在SpringBoot中使用HATEOAS的方法

    這篇文章主要介紹了在SpringBoot中使用HATEOAS的方法,HATEOAS是實(shí)現(xiàn)REST規(guī)范的一種原則,通過遵循HATEOAS規(guī)范,可以解決我們實(shí)際代碼實(shí)現(xiàn)的各種個(gè)問題,下文更多相關(guān)介紹,需要的小伙伴可以參考一下
    2022-05-05
  • Java處理延時(shí)任務(wù)的常用幾種解決方案

    Java處理延時(shí)任務(wù)的常用幾種解決方案

    本文主要介紹了Java處理延時(shí)任務(wù)的常用幾種解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Idea2019創(chuàng)建Springboot Web項(xiàng)目的方法步驟

    Idea2019創(chuàng)建Springboot Web項(xiàng)目的方法步驟

    這篇文章主要介紹了Idea2019創(chuàng)建Springboot Web項(xiàng)目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • mybatis-plus之如何根據(jù)數(shù)據(jù)庫(kù)主鍵定義字段類型

    mybatis-plus之如何根據(jù)數(shù)據(jù)庫(kù)主鍵定義字段類型

    這篇文章主要介紹了mybatis-plus之如何根據(jù)數(shù)據(jù)庫(kù)主鍵定義字段類型問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 簡(jiǎn)單了解Java的默認(rèn)和靜態(tài)方法

    簡(jiǎn)單了解Java的默認(rèn)和靜態(tài)方法

    這篇文章主要介紹了簡(jiǎn)單了解Java的默認(rèn)和靜態(tài)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Java全面分析面向?qū)ο笾庋b

    Java全面分析面向?qū)ο笾庋b

    或許大家都聽說過java是純面向?qū)ο笳Z言,面向?qū)ο笏枷胍簿褪俏覀兂Uf的OOP,我們聽說最多的思想就是繼承,封裝,多態(tài),今天我們來講一講封裝
    2022-04-04
  • Apache Shrio安全框架實(shí)現(xiàn)原理及實(shí)例詳解

    Apache Shrio安全框架實(shí)現(xiàn)原理及實(shí)例詳解

    這篇文章主要介紹了Apache Shrio安全框架實(shí)現(xiàn)原理及實(shí)例詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Java面試題沖刺第十一天--集合框架篇(2)

    Java面試題沖刺第十一天--集合框架篇(2)

    這篇文章主要為大家分享了最有價(jià)值的兩道集合框架的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java Timezone類常見問題_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java Timezone類常見問題_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Java Timezone類常見問題的相關(guān)資料,需要的朋友可以參考下
    2017-05-05

最新評(píng)論