Java以編程方式實現(xiàn)JAR文件的創(chuàng)建
大家好,我是指北君。
在這篇文章中,我們將介紹一下以編程方式創(chuàng)建jar文件的過程。在編寫軟件時,最終我們需要將其部署到生產(chǎn)狀態(tài)。在某些情況下,使用帶有獨立文件的classpath是可以的。通常情況下,處理一個文件會更方便。在Java的情況下,標(biāo)準(zhǔn)的方法是使用JAR、WAR或EAR文件。
基本過程是編寫清單,打開jar,添加內(nèi)容,最后保存jar。
Jar文件的解剖
jar文件是ZIP文件格式的擴(kuò)展,包含了一個清單文件。清單文件是JAR文件專用的特殊文件,可能包含各種設(shè)置。其中一些是主類、可選數(shù)據(jù)(即作者、版本等)和代碼簽名信息。
我們可以使用兼容zip的工具來查看和提取部分或全部存檔。我們還可以包括一個jars或libs子目錄,用于包含依賴性jar。由于jar是zip文件的擴(kuò)展,我們可以包括任何文件或目錄。
創(chuàng)建一個 JarTool 類
為了簡化創(chuàng)建JAR文件的過程,我們創(chuàng)建了一個單獨的、普通的舊Java對象(POJO)類,它封裝了我們的操作。我們可以將條目放入清單文件,創(chuàng)建JAR文件,添加文件或目錄。
我們還可以創(chuàng)建方法來執(zhí)行從JAR中刪除,甚至向現(xiàn)有的JAR追加條目,盡管這些操作需要完全讀取和重寫JAR。
JAR描述符
為了創(chuàng)建一個JAR文件,我們必須首先開始制定清單。
public?class?JarTool?{????
????private?Manifest?manifest?=?new?Manifest();
????public?void?startManifest()?{
????????manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION,?"1.0");
????}
}
如果我們希望jar是可執(zhí)行的,我們必須設(shè)置主類。
public?void?setMainClass(String?mainFQCN)?{
????if?(mainFQCN?!=?null?&&?!mainFQCN.equals(""))?{
????????manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS,?mainFQCN);
????}
}
另外,如果我們想指定額外的屬性,我們可以把它們添加到清單中,比如說。
addToManifest("Can-Redefine-Classes",?"true");
下面是這個方法。
public?void?addToManifest(String?key,?String?value)?{
?????manifest.getMainAttributes().put(new?Attributes.Name(key),?value);
}
打開JAR文件進(jìn)行編寫
隨著清單的完成,我們現(xiàn)在可以把條目寫到JAR文件中。要做到這一點,我們必須首先打開JAR。
public?JarOutputStream?openJar(String?jarFile)?throws?IOException?{????????
????return?new?JarOutputStream(new?FileOutputStream(jarFile),?manifest);
}
將文件添加到JAR中
在向JAR中添加文件時,Java使用Solaris風(fēng)格的文件名,使用正斜杠作為分隔符(/)。注意,我們可以添加任何類型的文件,包括其他JAR文件或空目錄。這對于包括依賴關(guān)系來說真的很方便。
另外,因為JAR文件是classpath的一種形式,我們必須指定我們希望在JAR中使用絕對路徑的哪一部分。對于我們的目的,根路徑將是我們項目的classpath。
了解了這一點,我們現(xiàn)在可以用這個方法完成我們的JarTool類。
public?void?addFile(JarOutputStream?target,?String?rootPath,?String?source)?
??throws?FileNotFoundException,?IOException?{
????String?remaining?=?"";
????if?(rootPath.endsWith(File.separator))?{
????????remaining?=?source.substring(rootPath.length());
????}?else?{
????????remaining?=?source.substring(rootPath.length()?+?1);
????}
????String?name?=?remaining.replace("\\","/");
????JarEntry?entry?=?new?JarEntry(name);
????entry.setTime(new?File(source).lastModified());
????target.putNextEntry(entry);
????
????BufferedInputStream?in?=?new?BufferedInputStream(new?FileInputStream(source));
????byte[]?buffer?=?new?byte[1024];
????while?(true)?{
????????int?count?=?in.read(buffer);
????????if?(count?==?-1)?{
????????????break;
????????}
????????target.write(buffer,?0,?count);
????}
????target.closeEntry();
????in.close();
}
一個工作實例
為了證明可執(zhí)行jar的最低要求,我們將編寫一個應(yīng)用類,然后看看它是如何工作的。
public?class?Driver?{
????public?static?void?main(String[]?args)?throws?IOException?{
????????JarTool?tool?=?new?JarTool();
????????tool.startManifest();
????????tool.addToManifest("Main-Class",?"com.javanorth.createjar.HelloWorld");
????????JarOutputStream?target?=?tool.openJar("HelloWorld.jar");
????????
????????tool.addFile(target,?System.getProperty("user.dir")?+?"\\src\\main\\java",
??????????System.getProperty("user.dir")?+?"\\src\\main\\java\\com\\javanorth\\createjar\\HelloWorld.class");
????????target.close();
????}
}
HelloWorld類是一個非常簡單的類,只有一個main()方法可以打印出文本。
public?class?HelloWorld?{
????public?static?void?main(String[]?args)?{
????????System.out.println("Hello?World!");
????}
}
為了證明它的作用,我們有這個例子。
$ javac -cp src/main/java src/main/java/com/javanorth/createjar/HelloWorld.java
$ javac -cp src/main/java src/main/java/com/javanorth/createjar/JarTool.java
$ javac -cp src/main/java src/main/java/com/javanorth/createjar/Driver.java
$ java -cp src/main/java com/javanorth/createjar/Driver
$ java -jar HelloWorld.jar
Hello World!
在這里,我們已經(jīng)編譯了每個類,然后執(zhí)行了Driver類,這將創(chuàng)建HelloWorld jar。最后,我們執(zhí)行了這個jar,結(jié)果是打印出了 "Hello World "信息。
上面的命令應(yīng)該從項目所在地執(zhí)行。
總結(jié)
在本教程中,我們看到了如何以編程方式創(chuàng)建一個jar文件,向其中添加文件,并最終執(zhí)行。
到此這篇關(guān)于Java以編程方式實現(xiàn)JAR文件的創(chuàng)建的文章就介紹到這了,更多相關(guān)Java創(chuàng)建JAR文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
分析java并發(fā)中的wait notify notifyAll
一個線程修改一個對象的值,而另一個線程則感知到了變化,然后進(jìn)行相應(yīng)的操作,這就是wait()、notify()和notifyAll()方法的本質(zhì)。本文將詳細(xì)來介紹它們概念實現(xiàn)以及區(qū)別2021-06-06
Java上傳文件錯誤java.lang.NoSuchMethodException的解決辦法
今天小編就為大家分享一篇關(guān)于Java上傳文件錯誤java.lang.NoSuchMethodException的解決辦法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01
feign 調(diào)用第三方服務(wù)中部分特殊符號未轉(zhuǎn)義問題
這篇文章主要介紹了feign 調(diào)用第三方服務(wù)中部分特殊符號未轉(zhuǎn)義問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
HttpClient實現(xiàn)遠(yuǎn)程調(diào)用
這篇文章主要為大家詳細(xì)介紹了HttpClient實現(xiàn)遠(yuǎn)程調(diào)用的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08
Java實現(xiàn)excel表格轉(zhuǎn)成json的方法
本篇文章主要介紹了Java實現(xiàn)excel表格轉(zhuǎn)成json的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09
Java設(shè)計模式之狀態(tài)模式(State模式)介紹
這篇文章主要介紹了Java設(shè)計模式之狀態(tài)模式(State模式)介紹,本文講解了何時使用狀態(tài)模式、如何使用狀態(tài)模式等內(nèi)容,需要的朋友可以參考下2015-03-03

