<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring Boot 打包成的可執(zhí)行 jar ,為什么不能被其他項(xiàng)目依賴?

          共 3328字,需瀏覽 7分鐘

           ·

          2021-01-15 08:11

          來自公眾號:江南一點(diǎn)雨

          前兩天被人問到這樣一個問題:

          “松哥,為什么我的 Spring Boot 項(xiàng)目打包成的 jar ,被其他項(xiàng)目依賴之后,總是報找不到類的錯誤?”

          大伙有這樣的疑問,就是因?yàn)檫€沒搞清楚可執(zhí)行 jar 和普通 jar 到底有什么區(qū)別?今天松哥就和大家來聊一聊這個問題。

          多了一個插件

          Spring Boot 中默認(rèn)打包成的 jar 叫做 可執(zhí)行 jar,這種 jar 不同于普通的 jar,普通的 jar 不可以通過 java-jar xxx.jar 命令執(zhí)行,普通的 jar 主要是被其他應(yīng)用依賴, SpringBoot 打成的 jar 可以執(zhí)行,但是不可以被其他的應(yīng)用所依賴,即使強(qiáng)制依賴,也無法獲取里邊的類。但是可執(zhí)行 jar 并不是 Spring Boot 獨(dú)有的,Java 工程本身就可以打包成可執(zhí)行 jar 。

          有的小伙伴可能就有疑問了,既然同樣是執(zhí)行 mvnpackage 命令進(jìn)行項(xiàng)目打包,為什么 Spring Boot 項(xiàng)目就打成了可執(zhí)行 jar ,而普通項(xiàng)目則打包成了不可執(zhí)行 jar 呢?

          這我們就不得不提 Spring Boot 項(xiàng)目中一個默認(rèn)的插件配置 spring-boot-maven-plugin ,這個打包插件存在 5 個方面的功能,從插件命令就可以看出:

          五個功能分別是:

          • build-info:生成項(xiàng)目的構(gòu)建信息文件 build-info.properties

          • repackage:這個是默認(rèn) goal,在?mvnpackage?執(zhí)行之后,這個命令再次打包生成可執(zhí)行的 jar,同時將?mvnpackage?生成的 jar 重命名為?*.origin

          • run:這個可以用來運(yùn)行 Spring Boot 應(yīng)用

          • start:這個在?mvn integration-test?階段,進(jìn)行?SpringBoot?應(yīng)用生命周期的管理

          • stop:這個在?mvn integration-test?階段,進(jìn)行?SpringBoot?應(yīng)用生命周期的管理

          這里功能,默認(rèn)情況下使用就是 repackage 功能,其他功能要使用,則需要開發(fā)者顯式配置。

          打包

          repackage 功能的 作用,就是在打包的時候,多做一點(diǎn)額外的事情:

          1. 首先?mvnpackage?命令 對項(xiàng)目進(jìn)行打包,打成一個?jar,這個?jar?就是一個普通的?jar,可以被其他項(xiàng)目依賴,但是不可以被執(zhí)行

          2. repackage?命令,對第一步 打包成的?jar?進(jìn)行再次打包,將之打成一個 可執(zhí)行?jar?,通過將第一步打成的?jar重命名為?*.original?文件

          舉個例子:

          對任意一個 Spring Boot 項(xiàng)目進(jìn)行打包,可以執(zhí)行 mvnpackage 命令,也可以直接在 IDEA 中點(diǎn)擊 package,如下 :

          打包成功之后, target 中的文件如下:

          這里有兩個文件,第一個 restful-0.0.1-SNAPSHOT.jar 表示打包成的可執(zhí)行 jar ,第二個 restful-0.0.1-SNAPSHOT.jar.original 則是在打包過程中 ,被重命名的 jar,這是一個不可執(zhí)行 jar,但是可以被其他項(xiàng)目依賴的 jar。通過對這兩個文件的解壓,我們可以看出這兩者之間的差異。

          兩種 jar 的比較

          可執(zhí)行 jar 解壓之后,目錄如下:

          可以看到,可執(zhí)行 jar 中,我們自己的代碼是存在 于 BOOT-INF/classes/ 目錄下,另外,還有一個 META-INF 的目錄,該目錄下有一個 MANIFEST.MF 文件,打開該文件,內(nèi)容如下:

          1. Manifest-Version: 1.0

          2. Implementation-Title: restful

          3. Implementation-Version: 0.0.1-SNAPSHOT

          4. Start-Class: org.javaboy.restful.RestfulApplication

          5. Spring-Boot-Classes: BOOT-INF/classes/

          6. Spring-Boot-Lib: BOOT-INF/lib/

          7. Build-Jdk-Spec: 1.8

          8. Spring-Boot-Version: 2.1.6.RELEASE

          9. Created-By: Maven Archiver 3.4.0

          10. Main-Class: org.springframework.boot.loader.JarLauncher

          可以看到,這里定義了一個 Start-Class,這就是可執(zhí)行 jar 的入口類, Spring-Boot-Classes 表示我們自己代碼編譯后的位置, Spring-Boot-Lib 則表示項(xiàng)目依賴的 jar 的位置。

          換句話說,如果自己要打一個可執(zhí)行 jar 包的話,除了添加相關(guān)依賴之外,還需要配置 META-INF/MANIFEST.MF 文件。

          這是可執(zhí)行 jar 的結(jié)構(gòu),那么不可執(zhí)行 jar 的結(jié)構(gòu)呢?

          我們首先將默認(rèn)的后綴 .original 除去,然后給文件重命名,重命名完成,進(jìn)行解壓:

          解壓后可以看到,不可執(zhí)行 jar 根目錄就相當(dāng)于我們的 classpath,解壓之后,直接就能看到我們的代碼,它也有 META-INF/MANIFEST.MF 文件,但是文件中沒有定義啟動類等。

          1. Manifest-Version: 1.0

          2. Implementation-Title: restful

          3. Implementation-Version: 0.0.1-SNAPSHOT

          4. Build-Jdk-Spec: 1.8

          5. Created-By: Maven Archiver 3.4.0

          注意

          這個不可以執(zhí)行 jar 也沒有將項(xiàng)目的依賴打包進(jìn)來。

          從這里我們就可以看出,兩個 jar ,雖然都是 jar 包,但是內(nèi)部結(jié)構(gòu)是完全不同的,因此一個可以直接執(zhí)行,另一個則可以被其他項(xiàng)目依賴。

          一次打包兩個 jar

          一般來說,Spring Boot 直接打包成可執(zhí)行 jar 就可以了,不建議將 Spring Boot 作為普通的 jar 被其他的項(xiàng)目所依賴。如果有這種需求,建議將被依賴的部分,單獨(dú)抽出來做一個普通的 Maven 項(xiàng)目,然后在 Spring Boot 中引用這個 Maven 項(xiàng)目。

          如果非要將 Spring Boot 打包成一個普通 jar 被其他項(xiàng)目依賴,技術(shù)上來說,也是可以的,給 spring-boot-maven-plugin 插件添加如下配置:

          1. org.springframework.boot

          2. spring-boot-maven-plugin

          3. exec

          配置的 classifier 表示可執(zhí)行 jar 的名字,配置了這個之后,在插件執(zhí)行 repackage 命令時,就不會給 mvnpackage 所打成的 jar 重命名了,所以,打包后的 jar 如下:

          第一個 jar 表示可以被其他項(xiàng)目依賴的 jar ,第二個 jar 則表示一個可執(zhí)行 jar。

          好了,關(guān)于 Spring Boot 中 jar 的問題,我們就說這么多,有問題歡迎留言討論。

          推薦閱讀

          分享基于 Spring Cloud +OAuth2 的權(quán)限管理系統(tǒng)

          鏈家程序員刪公司9TB 數(shù)據(jù) 被判7年

          工作10年后,再看String s = new String("xyz") 創(chuàng)建了幾個對象?

          SpringBoot集成WebSocket,實(shí)現(xiàn)后臺向前端推送信息

          SpringBoot 配置 ELK 環(huán)境

          給代碼寫注釋時有哪些講究?

          程序員該如何把 Windows 系統(tǒng)打造的跟 Mac 一樣牛逼?

          基于 SpringBoot,來實(shí)現(xiàn)MySQL讀寫分離技術(shù)

          瀏覽 19
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品久久久久久久久久久久久 | 在线无码一区二区三区四区 | 51午夜福利 | 日韩国产在线观看 | 苍井空在线一区二区 |