在這篇文章中,我們將介紹一下以編程方式創(chuàng)建jar文件的過(guò)程。在編寫(xiě)軟件時(shí),最終我們需要將其部署到生產(chǎn)狀態(tài)。在某些情況下,使用帶有獨(dú)立文件的classpath是可以的。通常情況下,處理一個(gè)文件會(huì)更方便。在Java的情況下,標(biāo)準(zhǔn)的方法是使用JAR、WAR或EAR文件。
基本過(guò)程是編寫(xiě)清單,打開(kāi)jar,添加內(nèi)容,最后保存jar。
Jar文件的解剖
jar文件是ZIP文件格式的擴(kuò)展,包含了一個(gè)清單文件。清單文件是JAR文件專(zhuān)用的特殊文件,可能包含各種設(shè)置。其中一些是主類(lèi)、可選數(shù)據(jù)(即作者、版本等)和代碼簽名信息。
我們可以使用兼容zip的工具來(lái)查看和提取部分或全部存檔。我們還可以包括一個(gè)jars或libs子目錄,用于包含依賴(lài)性jar。由于jar是zip文件的擴(kuò)展,我們可以包括任何文件或目錄。
創(chuàng)建一個(gè) JarTool
類(lèi)
為了簡(jiǎn)化創(chuàng)建JAR文件的過(guò)程,我們創(chuàng)建了一個(gè)單獨(dú)的、普通的舊Java對(duì)象(POJO)類(lèi),它封裝了我們的操作。我們可以將條目放入清單文件,創(chuàng)建JAR文件,添加文件或目錄。
我們還可以創(chuàng)建方法來(lái)執(zhí)行從JAR中刪除,甚至向現(xiàn)有的JAR追加條目,盡管這些操作需要完全讀取和重寫(xiě)JAR。
JAR描述符
為了創(chuàng)建一個(gè)JAR文件,我們必須首先開(kāi)始制定清單。
public class JarTool {
private Manifest manifest = new Manifest();
public void startManifest() {
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
}
}
如果我們希望jar是可執(zhí)行的,我們必須設(shè)置主類(lèi)。
public void setMainClass(String mainFQCN) {
if (mainFQCN != null && !mainFQCN.equals("")) {
manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, mainFQCN);
}
}
另外,如果我們想指定額外的屬性,我們可以把它們添加到清單中,比如說(shuō)。
addToManifest("Can-Redefine-Classes", "true");
下面是這個(gè)方法。
public void addToManifest(String key, String value) {
manifest.getMainAttributes().put(new Attributes.Name(key), value);
}
打開(kāi)JAR文件進(jìn)行編寫(xiě)
隨著清單的完成,我們現(xiàn)在可以把條目寫(xiě)到JAR文件中。要做到這一點(diǎn),我們必須首先打開(kāi)JAR。
public JarOutputStream openJar(String jarFile) throws IOException {
return new JarOutputStream(new FileOutputStream(jarFile), manifest);
}
將文件添加到JAR中
在向JAR中添加文件時(shí),Java使用Solaris風(fēng)格的文件名,使用正斜杠作為分隔符(/)。注意,我們可以添加任何類(lèi)型的文件,包括其他JAR文件或空目錄。這對(duì)于包括依賴(lài)關(guān)系來(lái)說(shuō)真的很方便。
另外,因?yàn)镴AR文件是classpath的一種形式,我們必須指定我們希望在JAR中使用絕對(duì)路徑的哪一部分。對(duì)于我們的目的,根路徑將是我們項(xiàng)目的classpath。
了解了這一點(diǎn),我們現(xiàn)在可以用這個(gè)方法完成我們的JarTool類(lèi)。
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();
}
一個(gè)工作實(shí)例
為了證明可執(zhí)行jar的最低要求,我們將編寫(xiě)一個(gè)應(yīng)用類(lèi),然后看看它是如何工作的。
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") + "srcmainjava",
System.getProperty("user.dir") + "srcmainjavacomjavanorthcreatejarHelloWorld.class");
target.close();
}
}
HelloWorld類(lèi)是一個(gè)非常簡(jiǎn)單的類(lèi),只有一個(gè)main()方法可以打印出文本。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
為了證明它的作用,我們有這個(gè)例子。
$ 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)編譯了每個(gè)類(lèi),然后執(zhí)行了Driver類(lèi),這將創(chuàng)建HelloWorld jar。最后,我們執(zhí)行了這個(gè)jar,結(jié)果是打印出了 "Hello World "信息。
上面的命令應(yīng)該從項(xiàng)目所在地執(zhí)行。
總結(jié)
在本教程中,我們看到了如何以編程方式創(chuàng)建一個(gè)jar文件,向其中添加文件,并最終執(zhí)行。
-
JAVA
+關(guān)注
關(guān)注
19文章
2975瀏覽量
105147 -
軟件
+關(guān)注
關(guān)注
69文章
5013瀏覽量
88075 -
文件
+關(guān)注
關(guān)注
1文章
570瀏覽量
24822 -
代碼
+關(guān)注
關(guān)注
30文章
4827瀏覽量
69052
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論