Java可執(zhí)行JAR包打包三種方式完全解析
引言:JAR 包打包的困擾與重要性
寫(xiě)完代碼只是萬(wàn)里長(zhǎng)征的第一步,如何將代碼打包成一個(gè) “開(kāi)箱即用” 的 JAR 文件,才是交付的關(guān)鍵一步。不少 Java 開(kāi)發(fā)者都有過(guò)這樣的經(jīng)歷:本地運(yùn)行得好好的程序,興高采烈地打包后,滿(mǎn)心歡喜地準(zhǔn)備部署,結(jié)果一運(yùn)行,報(bào)錯(cuò)ClassNotFoundException!這時(shí)候先別慌,大概率不是代碼出了岔子,而是 JAR 包沒(méi)打好。
在 Java 開(kāi)發(fā)中,JAR(Java Archive)包是一種非常常見(jiàn)的文件格式,它可以將多個(gè) Java 類(lèi)文件及其相關(guān)元數(shù)據(jù)和資源(如圖像和庫(kù))打包成單一文件,方便分發(fā)和部署。而對(duì)于 Maven 項(xiàng)目來(lái)說(shuō),打可執(zhí)行 JAR 包有多種方式。今天,我們就來(lái)深入對(duì)比三種主流方案:maven-jar-plugin(輕量外置依賴(lài))、maven-assembly-plugin(全家桶打包)和 maven-shade-plugin(高級(jí)防沖突版)。每種方式都會(huì)附上真實(shí)的 pom.xml 配置、執(zhí)行命令以及輸出結(jié)構(gòu),讓大家看完就能輕松上手。
方式一:maven-jar-plugin,輕量但依賴(lài)外置
原理剖析
maven-jar-plugin 是 Maven 的一個(gè)內(nèi)置插件,主要用于將項(xiàng)目編譯后的 class 文件及相關(guān)資源打包成 JAR 文件。不過(guò),它打包時(shí)僅包含項(xiàng)目自身的代碼和資源,第三方依賴(lài)則不會(huì)被打包進(jìn)去。那運(yùn)行時(shí)如何找到這些依賴(lài)呢?它通過(guò)在 MANIFEST.MF 文件中指定依賴(lài)的路徑,讓 JVM 在運(yùn)行時(shí)能從指定位置加載依賴(lài)。就好比你搬家時(shí),只帶走了自己的行李,而家具等大件物品則在新家附近的倉(cāng)庫(kù)放著,然后在入住清單上寫(xiě)清楚了倉(cāng)庫(kù)的位置,這樣入住時(shí)就能順利取到家具。
pom.xml 配置詳解
在 pom.xml 文件中,需要進(jìn)行如下配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>org.example.App</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>dependencies/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/dependencies/</outputDirectory>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>配置解釋如下:
mainClass:指定程序的入口類(lèi),也就是包含main方法的類(lèi)。addClasspath:設(shè)置為true表示將依賴(lài)的路徑添加到MANIFEST.MF文件的Class-Path中。classpathPrefix:指定依賴(lài)路徑的前綴,這里表示依賴(lài)包存放在dependencies/目錄下。maven-dependency-plugin:這個(gè)插件用于將項(xiàng)目的依賴(lài)復(fù)制到指定目錄,outputDirectory指定了依賴(lài)包的輸出目錄,includeScope設(shè)置為runtime表示只復(fù)制運(yùn)行時(shí)依賴(lài)的包。
打包后結(jié)構(gòu)與執(zhí)行命令
執(zhí)行 mvn clean package 命令后,在 target 目錄下會(huì)生成項(xiàng)目的 JAR 包以及 dependencies 目錄,dependencies 目錄中存放著項(xiàng)目的所有第三方依賴(lài)包。
JAR 包解壓后,目錄結(jié)構(gòu)大致如下:
├── META-INF
│ ├── MANIFEST.MF
│ └── maven
│ └── org.example
│ └── java-demo
│ ├── pom.properties
│ └── pom.xml
└── org
└── example
└── App.classMANIFEST.MF 文件內(nèi)容類(lèi)似:
Manifest-Version: 1.0 Created-By: Maven Jar Plugin 3.2.0 Build-Jdk-Spec: 17 Class-Path: dependencies/fastjson2-2.0.60.jar 第三方依賴(lài)包在這里 Main-Class: org.example.App 啟動(dòng)類(lèi)
執(zhí)行命令為:
java -jar java-demo-1.0-SNAPSHOT.jar
運(yùn)行時(shí),JVM 會(huì)根據(jù) MANIFEST.MF 文件中 Class-Path 指定的路徑去加載依賴(lài)包。
優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
JAR 包體積小:由于不包含第三方依賴(lài),JAR 包本身的大小相對(duì)較小,便于傳輸和存儲(chǔ)。
依賴(lài)清晰:依賴(lài)包單獨(dú)存放在
dependencies目錄中,依賴(lài)關(guān)系一目了然,方便管理和維護(hù)。
缺點(diǎn):
- 依賴(lài)位置限制:運(yùn)行時(shí)必須保證
dependencies目錄與 JAR 包在同一級(jí)目錄下,否則會(huì)因?yàn)檎也坏揭蕾?lài)而運(yùn)行失敗,這在部署時(shí)可能會(huì)帶來(lái)一些不便。例如在不同環(huán)境下部署,若目錄結(jié)構(gòu)發(fā)生變化,就需要手動(dòng)調(diào)整依賴(lài)目錄的位置。
- 依賴(lài)位置限制:運(yùn)行時(shí)必須保證
方式二:maven - assembly - plugin,全家桶打包
獨(dú)特的打包特點(diǎn)
maven-assembly-plugin 主打一個(gè) “全家桶” 概念,它生成的是所謂的 “fat jar”,也就是將項(xiàng)目代碼以及所有依賴(lài)的 class 文件全部打包到一個(gè) JAR 文件中。就好比你搬家時(shí),把所有的東西,包括家具、行李等一股腦都塞進(jìn)了一個(gè)超大的集裝箱里,這樣到了新家,只要這個(gè)集裝箱在,所有東西都在,完全不用擔(dān)心依賴(lài)丟失的問(wèn)題。在微服務(wù)架構(gòu)中,這種打包方式就非常實(shí)用,它可以確保各個(gè)服務(wù)獨(dú)立運(yùn)行,不用擔(dān)心依賴(lài)的傳遞和管理。
關(guān)鍵的 pom.xml 配置
在 pom.xml 文件中,配置如下:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<mainClass>org.example.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>配置解釋如下:
mainClass:指定程序的入口類(lèi),這是程序運(yùn)行的起點(diǎn)。descriptorRefs中的jar-with-dependencies:這是一個(gè)預(yù)定義的描述符,表示生成包含所有依賴(lài)的 JAR 包,使用這個(gè)描述符可以快速實(shí)現(xiàn)全家桶打包。execution部分:id是執(zhí)行的唯一標(biāo)識(shí)符,phase表示在 Maven 的package階段執(zhí)行該插件,goal為single表示生成一個(gè)獨(dú)立的聚合 JAR 包。
打包后的成果呈現(xiàn)
執(zhí)行 mvn clean package 命令后,在 target 目錄下會(huì)生成一個(gè)包含所有依賴(lài)的可執(zhí)行 JAR 包,例如 java-demo-1.0-SNAPSHOT-jar-with-dependencies.jar,同時(shí)還會(huì)有一個(gè)原始的不包含依賴(lài)的 JAR 包 java-demo-1.0-SNAPSHOT.jar。
可執(zhí)行 JAR 包解壓后,目錄結(jié)構(gòu)大致如下:
├── META-INF │ ├── MANIFEST.MF │ └── maven │ └── org.example │ └── java-demo │ ├── pom.properties │ └── pom.xml ├── org │ └── example │ └── App.class ├── com │ └── fasterxml │ └── json2 │ └── ... fastjson2相關(guān)類(lèi)文件 ├── org │ └── slf4j │ └── ... slf4j相關(guān)類(lèi)文件 └── ... 其他依賴(lài)的類(lèi)文件
MANIFEST.MF 文件內(nèi)容類(lèi)似:
Manifest-Version: 1.0 Created-By: Maven Assembly Plugin 3.4.2 Build-Jdk-Spec: 17 Main-Class: org.example.App
深入權(quán)衡利弊
優(yōu)點(diǎn):
部署便捷:只需一個(gè) JAR 文件,無(wú)需額外管理依賴(lài)包,部署時(shí)直接上傳運(yùn)行即可,大大簡(jiǎn)化了部署流程,降低了出錯(cuò)的概率。在生產(chǎn)環(huán)境中,運(yùn)維人員可以更方便地進(jìn)行部署和維護(hù),不用擔(dān)心依賴(lài)包的丟失或版本不一致的問(wèn)題。
依賴(lài)統(tǒng)一管理:所有依賴(lài)都在一個(gè) JAR 包內(nèi),不會(huì)出現(xiàn)依賴(lài)沖突(只要打包時(shí)不沖突),而且在不同環(huán)境中運(yùn)行時(shí),依賴(lài)的一致性有保障,避免了因環(huán)境差異導(dǎo)致的依賴(lài)問(wèn)題。
缺點(diǎn):
JAR 包體積大:由于包含了所有依賴(lài),JAR 包的體積通常會(huì)比較大,這在網(wǎng)絡(luò)傳輸和存儲(chǔ)時(shí)可能會(huì)帶來(lái)一些不便,比如部署到遠(yuǎn)程服務(wù)器時(shí),上傳速度會(huì)受到影響。
依賴(lài)類(lèi)合并沖突:在打包過(guò)程中,如果不同依賴(lài)中有同名的類(lèi),可能會(huì)導(dǎo)致沖突。雖然可以通過(guò)一些配置來(lái)解決部分沖突,但仍可能出現(xiàn)運(yùn)行時(shí)錯(cuò)誤,排查和解決這類(lèi)問(wèn)題往往比較困難。
方式三:maven - shade - plugin,高級(jí)防沖突版
核心技術(shù):類(lèi)重定位
maven-shade-plugin 可謂是一個(gè) “全能選手”,它不僅能像 maven-assembly-plugin 一樣將項(xiàng)目和依賴(lài)打包成一個(gè)可執(zhí)行的 “超級(jí) JAR”(也就是 “fat jar”),還自帶了一個(gè)高級(jí)技能 —— 類(lèi)重定位(Relocating Classes)。在復(fù)雜的項(xiàng)目中,不同依賴(lài)可能會(huì)引入相同庫(kù)的不同版本,或者不同依賴(lài)中有同名的類(lèi),這就好比兩個(gè)搬家的人都帶了同樣名字的家具,放在同一個(gè)屋子里肯定會(huì)亂套,程序運(yùn)行時(shí)就會(huì)報(bào)錯(cuò)。而 maven-shade-plugin 的類(lèi)重定位功能就像是給其中一個(gè)人的家具都貼上了特殊標(biāo)簽,改變了它們的 “名字”(類(lèi)名、包名),這樣就避免了沖突。它使用 ASM 字節(jié)碼操作庫(kù),在打包過(guò)程中動(dòng)態(tài)地修改類(lèi)的字節(jié)碼,將指定的類(lèi)或包移動(dòng)到新的命名空間 ,從而實(shí)現(xiàn)不同版本依賴(lài)的共存。
詳細(xì)配置步驟
在 pom.xml 文件中,配置如下:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.example.App</mainClass>
</transformer>
</transformers>
<relocations>
<relocation>
<pattern>org.old.package</pattern>
<shadedPattern>org.new.shaded.package</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>配置解釋如下:
transformers中的ManifestResourceTransformer:用于修改MANIFEST.MF文件,設(shè)置mainClass為程序的入口類(lèi),這樣生成的 JAR 包就可以直接通過(guò)java -jar命令運(yùn)行。relocations:這是類(lèi)重定位的核心配置部分,pattern指定需要重定位的原始包名,shadedPattern指定重定位后的目標(biāo)包名。比如項(xiàng)目中org.old.package下的類(lèi)可能與其他依賴(lài)沖突,就可以將其重定位到org.new.shaded.package。filters:用于過(guò)濾資源,這里配置排除META-INF目錄下的簽名文件(.SF、.DSA、.RSA),因?yàn)檫@些文件在合并 JAR 包時(shí)可能會(huì)引起沖突。
實(shí)際應(yīng)用案例分析
假設(shè)有一個(gè)電商項(xiàng)目,使用了一個(gè)老版本的支付 SDK(old-payment-sdk),它依賴(lài) guava 18.0 版本。而項(xiàng)目中其他功能需要使用 guava 32.0 版本來(lái)獲得新特性和性能優(yōu)化。在沒(méi)有使用 maven-shade-plugin 之前,項(xiàng)目啟動(dòng)時(shí)就會(huì)報(bào)錯(cuò),因?yàn)椴煌姹镜?guava 沖突了,導(dǎo)致一些方法找不到或者類(lèi)加載錯(cuò)誤。
使用 maven-shade-plugin 進(jìn)行配置:
<configuration>
<relocations>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>com.shaded.guava18.com.google.common</shadedPattern>
<includes>
<include>com.old.payment:old-payment-sdk</include>
</includes>
</relocation>
</relocations>
</configuration>配置解釋?zhuān)哼@里將 old-payment-sdk 及其依賴(lài)中的 com.google.common 包下的所有類(lèi)重定位到 com.shaded.guava18.com.google.common 包下。includes 標(biāo)簽指定了只對(duì) old-payment-sdk 進(jìn)行重定位操作,這樣項(xiàng)目中其他地方使用的 guava 32.0 版本就不會(huì)受到影響。
執(zhí)行 mvn clean package 命令后,生成的 JAR 包中就包含了兩個(gè)版本的 guava,并且不會(huì)沖突。在代碼中,訪問(wèn) old-payment-sdk 中的 guava 相關(guān)類(lèi)時(shí),需要使用重定位后的包名,比如原來(lái) com.google.common.collect.Lists 現(xiàn)在要寫(xiě)成 com.shaded.guava18.com.google.common.collect.Lists 。通過(guò)這種方式,成功解決了依賴(lài)沖突問(wèn)題,項(xiàng)目能夠正常啟動(dòng)和運(yùn)行 。
對(duì)比總結(jié):選擇最合適的打包方式
特性全面對(duì)比
為了更直觀地對(duì)比這三種插件,我們將它們?cè)诖虬笮?、依?lài)處理、沖突解決、部署便捷性等方面的特性整理成如下表格:
| 特性 | maven - jar - plugin | maven - assembly - plugin | maven - shade - plugin |
|---|---|---|---|
| 打包大小 | 較小,不包含依賴(lài) | 較大,包含所有依賴(lài) | 較大,包含所有依賴(lài) |
| 依賴(lài)處理 | 依賴(lài)外置,在MANIFEST.MF指定路徑 | 依賴(lài)內(nèi)置,全部打包進(jìn) JAR | 依賴(lài)內(nèi)置,全部打包進(jìn) JAR |
| 沖突解決 | 無(wú)特殊沖突解決機(jī)制 | 可能出現(xiàn)依賴(lài)類(lèi)合并沖突 | 通過(guò)類(lèi)重定位解決依賴(lài)沖突 |
| 部署便捷性 | 需保證依賴(lài)目錄與 JAR 包在同一級(jí),部署相對(duì)復(fù)雜 | 只需一個(gè) JAR 文件,部署便捷 | 只需一個(gè) JAR 文件,部署便捷 |
| 適用場(chǎng)景 | 依賴(lài)管理簡(jiǎn)單,對(duì) JAR 包大小敏感,且部署環(huán)境能保證依賴(lài)路徑一致性的項(xiàng)目 | 依賴(lài)管理不太復(fù)雜,追求部署便捷性,對(duì) JAR 包大小不太敏感的項(xiàng)目 | 依賴(lài)復(fù)雜,存在依賴(lài)沖突風(fēng)險(xiǎn),需要確保不同版本依賴(lài)共存的項(xiàng)目 |
根據(jù)場(chǎng)景選擇
針對(duì)不同項(xiàng)目場(chǎng)景,選擇合適的打包方式可以事半功倍:
小型項(xiàng)目:如果項(xiàng)目依賴(lài)較少,且對(duì) JAR 包大小比較敏感,同時(shí)部署環(huán)境能保證依賴(lài)路徑的一致性,那么
maven - jar - plugin是一個(gè)不錯(cuò)的選擇。它可以讓 JAR 包保持較小的體積,同時(shí)依賴(lài)管理也相對(duì)簡(jiǎn)單。例如一個(gè)簡(jiǎn)單的命令行工具項(xiàng)目,依賴(lài)的第三方庫(kù)很少,使用maven - jar - plugin打包后,方便在不同環(huán)境中快速部署和運(yùn)行。大型項(xiàng)目:對(duì)于大型項(xiàng)目,尤其是微服務(wù)架構(gòu)中的各個(gè)服務(wù),
maven - assembly - plugin或maven - shade - plugin更為合適。如果依賴(lài)管理相對(duì)簡(jiǎn)單,沒(méi)有復(fù)雜的依賴(lài)沖突問(wèn)題,maven - assembly - plugin的 “全家桶” 打包方式可以簡(jiǎn)化部署流程,提高部署效率。比如一個(gè)電商微服務(wù)項(xiàng)目,各個(gè)服務(wù)之間依賴(lài)明確,使用maven - assembly - plugin打包后,每個(gè)服務(wù)都可以獨(dú)立部署,互不干擾。依賴(lài)復(fù)雜項(xiàng)目:當(dāng)項(xiàng)目依賴(lài)復(fù)雜,存在不同版本依賴(lài)沖突的風(fēng)險(xiǎn)時(shí),
maven - shade - plugin無(wú)疑是最佳選擇。它通過(guò)類(lèi)重定位功能,能夠有效地解決依賴(lài)沖突問(wèn)題,確保項(xiàng)目的穩(wěn)定運(yùn)行。例如一個(gè)大型的企業(yè)級(jí)應(yīng)用,集成了多個(gè)不同團(tuán)隊(duì)開(kāi)發(fā)的模塊,每個(gè)模塊可能依賴(lài)不同版本的相同庫(kù),使用maven - shade - plugin可以讓這些依賴(lài)和諧共處,避免因沖突導(dǎo)致的運(yùn)行時(shí)錯(cuò)誤 。
在實(shí)際項(xiàng)目中,選擇合適的打包方式至關(guān)重要。希望通過(guò)本文的介紹,大家能根據(jù)項(xiàng)目的具體需求,靈活運(yùn)用這三種打包方式,順利完成項(xiàng)目的交付。如果在實(shí)踐過(guò)程中有任何疑問(wèn)或心得,歡迎在評(píng)論區(qū)留言分享,讓我們一起進(jìn)步!
結(jié)語(yǔ):打包之路,從此暢通
JAR 包的打包方式各有千秋,maven-jar-plugin 以小巧輕便見(jiàn)長(zhǎng),適用于依賴(lài)管理簡(jiǎn)單的項(xiàng)目;maven-assembly-plugin “全家桶” 式的打包風(fēng)格,讓部署變得輕而易舉,是追求便捷部署項(xiàng)目的首選;而 maven-shade-plugin 憑借強(qiáng)大的類(lèi)重定位技術(shù),在復(fù)雜依賴(lài)的項(xiàng)目中發(fā)揮著關(guān)鍵作用,解決了令人頭疼的依賴(lài)沖突問(wèn)題。
在實(shí)際的項(xiàng)目開(kāi)發(fā)中,大家要根據(jù)項(xiàng)目的具體情況,如依賴(lài)的復(fù)雜程度、JAR 包大小的限制、部署環(huán)境的要求等,靈活選擇合適的打包方式。希望大家通過(guò)這篇文章,對(duì)這三種主流的打包方式有了更深入的理解,在今后的 Java 開(kāi)發(fā)中,能夠輕松應(yīng)對(duì) JAR 包打包問(wèn)題,讓項(xiàng)目的交付更加順利!如果在實(shí)踐過(guò)程中遇到任何問(wèn)題,歡迎隨時(shí)在評(píng)論區(qū)留言,我們一起探討解決 。
到此這篇關(guān)于Java可執(zhí)行JAR包打包三種方式的文章就介紹到這了,更多相關(guān)Java可執(zhí)行JAR包打包內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot項(xiàng)目開(kāi)發(fā)中常用的依賴(lài)
這篇文章主要介紹了SpringBoot項(xiàng)目開(kāi)發(fā)中常用的依賴(lài)詳解,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
SpringBoot請(qǐng)求轉(zhuǎn)發(fā)的方式小結(jié)
本文主要介紹了SpringBoot請(qǐng)求轉(zhuǎn)發(fā)的方式,一共有兩大類(lèi),一種是controller控制器轉(zhuǎn)發(fā)一種是使用HttpServletRequest進(jìn)行轉(zhuǎn)發(fā),本文就詳細(xì)的介紹一下,感興趣的可以了解一下2023-09-09
使用Java實(shí)現(xiàn)KMZ和KML數(shù)據(jù)的直接解析
本文主要講解如何用JAVA語(yǔ)言,直接解析KMZ數(shù)據(jù),文章首先介紹google地圖中的KMZ和KML數(shù)據(jù),然后使用代碼的方式實(shí)現(xiàn)數(shù)據(jù)的解析,最后展示解析成果以及如何將數(shù)據(jù)轉(zhuǎn)換成空間WKT數(shù)據(jù),需要的朋友可以參考下2024-06-06
Spring事務(wù)執(zhí)行流程及如何創(chuàng)建事務(wù)
這篇文章主要介紹了Spring事務(wù)執(zhí)行流程及如何創(chuàng)建事務(wù),幫助大家更好的理解和學(xué)習(xí)使用spring框架,感興趣的朋友可以了解下2021-03-03
Java中Easypoi實(shí)現(xiàn)excel多sheet表導(dǎo)入導(dǎo)出功能
這篇文章主要介紹了Java中Easypoi實(shí)現(xiàn)excel多sheet表導(dǎo)入導(dǎo)出功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
MyBatis Plus 入門(mén)使用詳細(xì)教程
這篇文章主要介紹了MyBatis Plus 入門(mén)使用詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
java編程FinalReference與Finalizer原理示例詳解
這篇文章主要為大家介紹了java編程FinalReference與Finalizer的核心原理以及示例源碼的分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-01-01
Springboot整合nacos報(bào)錯(cuò)無(wú)法連接nacos的解決
這篇文章主要介紹了Springboot整合nacos報(bào)錯(cuò)無(wú)法連接nacos的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06

