一、什么是jar包
jar包就是 Java Archive File,顧名思義,它的應(yīng)用是與 Java 息息相關(guān)的,是 Java 的一種文檔格式,是一種與平臺(tái)無(wú)關(guān)的文件格式,可將多個(gè)文件合成一個(gè)文件。jar 包與 zip 包非常相似——準(zhǔn)確地說(shuō),它就是 zip 包,所以叫它文件包。jar 與 zip 唯一的區(qū)別就是在 jar 文件的內(nèi)容中,包含了一個(gè) META-INF/MANIFEST.MF 文件,該文件是在生成 jar 文件的時(shí)候自動(dòng)創(chuàng)建的,作為jar里面的"詳情單",包含了該Jar包的版本、創(chuàng)建人和類搜索路徑Class-Path等信息,當(dāng)然如果是可執(zhí)行Jar包,會(huì)包含Main-Class屬性,表明Main方法入口,尤其是較為重要的Class-Path和Main-Class。
此外,值得注意的是,因?yàn)閖ar包主要是對(duì)class文件進(jìn)行打包,而java編譯生成的class文件是平臺(tái)無(wú)關(guān)的,這就意味著jar包是跨平臺(tái)的,所以不必關(guān)心涉及具體平臺(tái)的問(wèn)題。說(shuō)到j(luò)ar里面的文件,咱們來(lái)看看最普通的一個(gè)帶有靜態(tài)頁(yè)面的springboot項(xiàng)目jar里面的內(nèi)容,就會(huì)發(fā)現(xiàn)解壓出來(lái)的jar并不簡(jiǎn)單,為了貼近實(shí)際咱們未做任何刪減,可以看到有很多東西
只需要運(yùn)行如下指令,就能看到j(luò)ar里面的內(nèi)容(調(diào)用jar指令的前提是已經(jīng)配置了jdk的環(huán)境變量)
jar -tf springbootdemo-0.0.1-SNAPSHOT.jar
其中-tf 后接的jar就是我們要查看的jar。
大致看看里面的東西我們可以發(fā)現(xiàn),除了.MF以及.class文件之外,jar還能打包靜態(tài)資源文件如.html、.css以及.js等項(xiàng)目所需的一切,這也就意味著咱們能將自己的項(xiàng)目打成jar,即不管是web應(yīng)用還是底層框架,都能打成jar包。
有的jar包是可以直接通過(guò) java -jar 指令來(lái)執(zhí)行的。我們都知道,有的類之所以能夠執(zhí)行,是因?yàn)樗媚阌衜ain函數(shù),該函數(shù)是程序的入口,同理,可執(zhí)行的jar包中肯定是有某個(gè).class文件提供了main函數(shù)才使得其可執(zhí)行。那么問(wèn)題來(lái)了,一個(gè)jar里面可能存在多個(gè).class文件都有main函數(shù)的情況,我怎么知道該執(zhí)行哪個(gè)?其實(shí)答案非常簡(jiǎn)單,就是看前面說(shuō)的MANIFEST.MF里面的Main-Class屬性,它會(huì)指定函數(shù)入口。
二、為什么要打jar包
當(dāng)我們開(kāi)發(fā)了一個(gè)程序以后,程序中有很多的類,如果需要提供給別人使用,發(fā)給對(duì)方一大堆源文件是非常不好的,因此通常需要把這些類以及相關(guān)的資源文件打包成一個(gè) jar 包,把這個(gè) jar 包提供給別人使用,同時(shí)提供給使用者清晰的文檔。這樣他人在拿到我們提供的jar之后,就能方便地進(jìn)行調(diào)用。而且安全。能夠?qū)AR文件進(jìn)行數(shù)字簽名,只讓能夠識(shí)別數(shù)字簽名的用戶使用里面的東西。
因此,建議大家在平時(shí)寫代碼搬磚的時(shí)候,注意把自己代碼的通用部分抽離出來(lái),主鍵積累一些通用的util類,將其逐漸模塊化,最后打成jar包供自己在別的項(xiàng)目或者模塊中使用,同時(shí)不斷打磨jar里面的內(nèi)容,將其做得越來(lái)越容易理解和通用,這樣的好處是除了會(huì)對(duì)你的代碼重構(gòu)能力以及模塊抽象能力有很好的幫助之外,更是一種從長(zhǎng)期解放你的重復(fù)工作量,讓你有更多的精力去做其他事情的方式,甚至當(dāng)你抽象出業(yè)內(nèi)足夠通用的jar之后,jar包還能為你帶來(lái)意想不到的利潤(rùn)(當(dāng)然公司里該保密的東西還是得保密的)。這也是java發(fā)展得如此之好的原因,無(wú)論出于盈利或者非盈利的目的,將自己的通用工具或者框架抽取出來(lái),打成jar包供他人調(diào)用,使得整個(gè)java生態(tài)圈變得越來(lái)越強(qiáng)大–幾乎很多業(yè)務(wù)場(chǎng)景都能找到對(duì)應(yīng)的jar包。
三、如何打jar包
1、通過(guò)jdk命令
A:含有多個(gè)類的jar,類之間存在調(diào)用關(guān)系
先創(chuàng)建一個(gè)java項(xiàng)目,編寫兩個(gè)非常簡(jiǎn)單的類,Welcome.java和Teacher.jar,其中Welcome類在main函數(shù)里調(diào)用了Teacher類的靜態(tài)方法greeting
Welcome.java
packagecom.imooc.jardemo1;
importcom.imooc.jardemo1.impl.Teacher;
publicclassWelcome{
publicstaticvoidmain(String[] args){
? ? ? ? Teacher.greeting();
? ? }
}
Teacher.java
packagecom.imooc.jardemo1.impl;
publicclassTeacher{
publicstaticvoidgreeting(){
System.out.printf("Welcome!");
? ? }
}
在命令行里,去到項(xiàng)目的src路徑下,執(zhí)行javac指令
javac com/imooc/jardemo1/Welcome.java
此時(shí)就會(huì)生成與這兩個(gè)類相對(duì)應(yīng)的.class字節(jié)碼文件
由于jvm實(shí)際解析的是.class字節(jié)碼文件而非.java文件,且jar中最好不要包含代碼源文件,我們來(lái)將.class文件打個(gè)jar包,在src根目錄下執(zhí)行如下指令
jar -cvf welcome.jar com/imooc/jardemo1/Welcome.class com/imooc/jardemo1/impl/Teacher.class
c表示要?jiǎng)?chuàng)建一個(gè)新的jar包,v表示創(chuàng)建的過(guò)程中在控制臺(tái)輸出創(chuàng)建過(guò)程的一些信息,f表示給生成的jar包命名
打jar的時(shí)候,會(huì)生成一個(gè)META-INF的目錄,里面有MANIFEST.MF這個(gè)清單列表。內(nèi)容為:
Manifest-Version: 1.0 Created-By: 11 (Oracle Corporation)
此時(shí)生成的jar包還不能執(zhí)行,因?yàn)槿鄙僭蹅兿惹罢f(shuō)的Main-Class屬性,導(dǎo)致jar被執(zhí)行的時(shí)候,不知道執(zhí)行哪個(gè)main函數(shù)。因此我們需要加上Main-Class,后接main函數(shù)所在類的全路徑名(注意冒號(hào)之后一定要跟英文的空格,整個(gè)文件最后有一行空行)。
Manifest-Version: 1.0 Created-By: 11 (Oracle Corporation) Main-Class:
com.imooc.jardemo1.Welcome
添加完成后,重新執(zhí)行指令打包,這次咱們?cè)诖虬噶罾锒嗉右粋€(gè)參數(shù),即多傳入修改完成后的MANIFEST.MF文件
jar -cvfm welcome.jar META-INF/MANIFEST.MF com/imooc/jardemo1/Welcome.class com/imooc/jardemo1/impl/Teacher.class
其中多了一個(gè)參數(shù)m,表示要定義MANIFEST文件。之后再重新執(zhí)行
java -jar welcome.jar
就會(huì)發(fā)現(xiàn)jar已成功執(zhí)行