淺談 java 中構建可執行 jar 包的幾種方式

        有時候,因爲項目的須要,咱們會將源碼編譯後以工具包(class打成jar包)的形式對外提供,此時,
你的 jar 包不必定要是可執行的,只要能經過編譯,能被別人以 import 的方式調用就好了。但還有的
狀況是,咱們的 jar 包是要可執行的,即能直接在 cmd 下直接運行。前者的打包很簡單,在 eclipse 中,
直接選中要打包的 java 文件和其它資源、依賴文件, export → Java → JAR file 便可。須要注意的是,
這種方式導出的 jar 包是不可執行的,好比你執行以下的語句:
java -jar test.jar
java -classpath test.jar com.test_maven.App
會直接報錯:沒法找到主類或者找不到 xxx 依賴包/類,這是因爲你沒有定義 MANIFEST.MF 資源描述文件所致,
或者你直接把依賴的 jar 包打進了你最終的 jar,而這種嵌套的依賴 jar 包是不能直接被程序 import 識別的。
        下面咱們看看如何在 eclipse 中構建一個可執行的 jar 包。html

(1)最簡單的仍是依賴於 eclipse 的導出功能java

export → java → Runnable JAR file,這種形式的導出程序員

能夠經過 lanuch configuration 指定一個 MainClass,並會自動生成 MANIFEST.MF ,並且會幫你把依賴的 jar 包解壓出來,一併打進最終的 jar 包,這樣就能被你的代碼 import 引用了。apache

(2)上述方法是 eclipse 自帶的,eclipse 也有個專門的插件叫作 Fat Jar,支持許多定製化的功能,json

具體請參見下面的連接。可是這個插件有些缺陷,好比修改源碼後若是你不 clean & rebuild project,緩存

 它會使用緩存從新打包,這樣你的編譯代碼仍是老的,會形成執行錯誤,並且這樣是十分不方便的。oracle

用Fat Jar Eclipse Plug-In打包可執行jar文件eclipse

http://8366.iteye.com/blog/480652maven

(3)稍微大點的項目都會用 maven 或者 ant 來構建,在 maven 工程中,咱們也能夠很方便的打包成可執行的 jar
包。默認Maven生成的JAR包只包含了編譯生成的.class文件和項目資源文件,而要獲得一個能夠直接在命令行經過
java命令運行的JAR文件,還要知足兩個條件:工具

  • JAR包中的/META-INF/MANIFEST.MF元數據文件必須包含Main-Class信息。
  • 項目全部的依賴都必須在Classpath中,其能夠經過 MANIFEST.MF 指定或者隱式設置。

Maven有好幾個插件能幫助用戶完成上述任務,不過用起來最方便的仍是maven-shade-plugin,它可讓用戶配置
Main-Class的值,而後在打包的時候將值填入/META-INF/MANIFEST.MF文件。關於項目的依賴,它很聰明地將依賴
JAR文件所有解壓後,再將獲得的.class文件連同當前項目的.class文件一塊兒合併到最終的CLI包中,這樣,在執行CLI JAR文件的時候,全部須要的類就都在Classpath中了。下面是一個配置樣例:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>1.4</version>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
        <configuration>
          <transformers>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
              <mainClass>com.juvenxu.mavenbook.HelloWorldCli</mainClass>
            </transformer>
          </transformers>
        </configuration>
      </execution>
    </executions>
  </plugin>

上述例子中的,個人Main-Class是com.juvenxu.mavenbook.HelloWorldCli,構建完成後,對應於一個常規的
hello-world-1.0.jar文件,我還獲得了一個hello-world-1.0-cli.jar文件。細心的讀者可能已經注意到了,這裏用的
是cli這個classifier。最後,我能夠經過java -jar hello-world-1.0-cli.jar命令運行程序。固然了,若是你須要更加自由
的打包方式,那就用 maven-assembly-plugin 吧。它支持各類打包文件格式,包括zip、tar.gz、tar.bz2等等,經過一個打包
描述文件(例如 src/main/assembly.xml),它可以幫助用戶選擇具體打包哪些文件集合、依賴、模塊、和甚至本地倉庫文件,

每一個項的具體打包路徑用戶也能自由控制。好比下面的配置經過設置 assembly 文件的配置節點 dependencySets/includes,來實現 maven build 生成的 jar 包只包含指定的 jar 依賴。

<assembly ... ooxx>
	<fileSets>
	</fileSets>
	<dependencySets>
        <dependencySet>
        	<unpack>false</unpack> 
            <outputDirectory>lib</outputDirectory>
            <scope>runtime</scope>
		    <includes>  
		        <include>groupId:artifactId</include>  
		    </includes>
        </dependencySet>
    </dependencySets>
</assembly>

具體請參見:
Maven實戰(九)——打包的技巧

http://www.infoq.com/cn/news/2011/06/xxb-maven-9-package

maven發佈 jar類型的工程

http://mengyunshuitian.iteye.com/blog/1759864

maven assembly plugin dependencySet with transitive dependencies

http://stackoverflow.com/questions/22505886/maven-assembly-plugin-dependencyset-with-transitive-dependencies

http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#dependencySet

(4)可使用兩個 Maven 插件幫助您完成:maven-jar-plugin 和 maven-dependency-plugin。
maven-jar-plugin 能夠作不少事情,但在這裏,咱們只對使用它來修改默認 MANIFEST.MF 文件的內容感興趣。
在您的 POM 文件的插件部分添加清單 1 所示代碼:
清單 1. 使用 maven-jar-plugin 修改 MANIFEST.MF

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
                <mainClass>com.mypackage.MyClass</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

全部 Maven 插件經過一個 <configuration> 元素公佈了其配置,在本例中,maven-jar-plugin 修改它的 archive 屬性,
特別是存檔文件的 manifest 屬性,它控制 MANIFEST.MF 文件的內容。包括 3 個元素:
addClassPath:將該元素設置爲 true 告知 maven-jar-plugin 添加一個 Class-Path 元素到 MANIFEST.MF 文件,以及在 
Class-Path 元素中包括全部依賴項。
classpathPrefix:若是您計劃在同一目錄下包含有您的全部依賴項,做爲您將構建的 JAR,那麼您能夠忽略它;不然使用 
classpathPrefix 來指定全部依賴 JAR 文件的前綴。在清單 1 中,classpathPrefix 指出,相對存檔文件,全部的依賴項
應該位於 「lib」 文件夾。
mainClass:當用戶使用 lib 命令執行 JAR 文件時,使用該元素定義將要執行的類名。
當您使用這 3 個元素配置好了 MANIFEST.MF 文件以後,下一步是將全部的依賴項複製到 lib 文件夾。爲此,使用 
maven-dependency-plugin,如清單 2 所示:
清單 2. 使用 maven-dependency-plugin 將依賴項複製到庫

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy</id>
            <phase>install</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>
                  ${project.build.directory}/lib
                </outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

maven-dependency-plugin 有一個 copy-dependencies,目標是將您的依賴項複製到您所選擇的目錄。本例中,我將依賴項複製到 
build 目錄下的 lib 目錄(project-home/target/lib)。
將您的依賴項和修改的 MANIFEST.MF 放在適當的位置後,您就能夠用一個簡單的命令啓動應用程序:
java -jar jarfilename.jar
更多技巧,您能夠參考:

關於 Apache Maven 您不知道的 5 件事

http://www.ibm.com/developerworks/cn/java/j-5things13/

(5)固然了,若是你不怕麻煩的話,手動打包,本身創建、維護 MANIFEST.MF 文件也是能夠的,你能夠參考以下連接:

http://blog.csdn.net/mango_song/article/details/8531389

http://gushuizerotoone.iteye.com/blog/1757002

(6)把包發佈到 nexus

項目上右鍵 → run as → maven build

附:Maven的座標GAV(groupId, artifactId, version)定義

pom定義了最小的maven元素,容許groupId,artifactId,version。在 POM 中,groupId, artifactId, packaging, version 叫做 maven 座標,它能惟一的肯定一個項目。有了 maven 座標,咱們就能夠用它來指定咱們的項目所依賴的其餘項目,插件,或者父項目。通常 maven 座標寫成以下的格式:
groupId:artifactId:packaging:version

  • groupId: 項目或者組織的惟一標誌,而且配置時生成的路徑也是由今生成,如org.codehaus.mojo生成的相對路徑爲:/org/codehaus/mojo
  • artifactId: 項目的通用名稱
  • version: 項目的版本
  • packaging: 打包的機制,如pom, jar, maven-plugin, ejb, war, ear, rar, par
  • classifier: 分類,它表示在相同版本下針對不一樣的環境或者jdk使用的jar,若是配置了這個元素,則會將這個元素名在加在最後來查找相應的jar,例如:
<dependency>  
                <groupId>net.sf.json-lib</groupId>   
                <artifactId>json-lib</artifactId>   
                <version>2.2.2</version>  
                <classifier>jdk15</classifier>    
            </dependency>

這樣配置便可找到json-lib-2.2.2-jdk15.jar ,其餘的就不解釋了,應該明白他的用途了吧。
POM關係:

主要爲依賴,繼承,合成

REF:

使用maven插件對java工程進行打包

http://chenzhou123520.iteye.com/blog/1706242   

關於如何從jar包中讀取配置、屬性文件,請參考:

http://my.oschina.net/leejun2005/blog/95186

Apache Maven 入門篇(下)

http://www.oracle.com/technetwork/cn/community/java/apache-maven-getting-started-2-405568-zhs.html

maven 配置篇 之pom.xml(一)

http://zyl.iteye.com/blog/41754

Maven最佳實踐:劃分模塊

http://juvenshun.iteye.com/blog/305865

在Eclipse中建立Maven多模塊工程的例子

http://www.blogways.net/blog/2013/05/13/maven-multi-modules-demo.html

每一個程序員都該學會的Maven知識

https://mp.weixin.qq.com/s/UnMyH65RtWPHdRHMfIsxlg

Maven 虐我千百遍,我待 Maven 如初戀

http://bit.ly/2JRGrIY

相關文章
相關標籤/搜索