1. 程式人生 > >maven-shade-plugin 使用maven外掛對java工程進行打包

maven-shade-plugin 使用maven外掛對java工程進行打包

現在基本上都是採用maven來進行開發管理,我有一個需求是需要把通過maven管理的java工程打成可執行的jar包,這樣也就是說必需把工程依賴的jar包也一起打包。而使用maven預設的package命令構建的jar包中只包括了工程自身的class檔案,並沒有包括依賴的jar包。我們可以通過配置外掛來對工程進行打包,pom具體配置如下:

maven-assembly-plugin

Xml程式碼  收藏程式碼
  1. <plugin>  
  2.     <artifactId>maven-assembly-plugin</artifactId>  
  3.     <configuration
    >  
  4.         <appendAssemblyId>false</appendAssemblyId>  
  5.         <descriptorRefs>  
  6.             <descriptorRef>jar-with-dependencies</descriptorRef>  
  7.         </descriptorRefs>  
  8.         <archive>  
  9.             <manifest>  
  10.                 <mainClass
    >com.chenzhou.examples.Main</mainClass>  
  11.             </manifest>  
  12.         </archive>  
  13.     </configuration>  
  14.     <executions>  
  15.         <execution>  
  16.             <id>make-assembly</id>  
  17.             <phase>package</phase>  
  18.             <
    goals>  
  19.                 <goal>assembly</goal>  
  20.             </goals>  
  21.         </execution>  
  22.     </executions>  
  23. </plugin>  

其中<mainClass></mainClass>的值表示此工程的入口類,也就是包含main方法的類,在我的例子中就是com.chenzhou.examples.Main。配置完pom後可以通過執行mvn assembly:assembly命令來啟動外掛進行構建。構建成功後會生成jar包,這樣我們就可以在命令列中通過java -jar XXX.jar來執行jar件了。 

不過使用此外掛會有一些問題:我在工程中依賴了spring框架的jar包,我打包成功後使用命令來呼叫jar包時報錯如下(內網環境):

Shell程式碼  收藏程式碼
  1. org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'http://www.springframework.org/schema/beans/spring-beans-3.0.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.  

關於此問題報錯的原因,我在網上找到一篇文章對此有比較詳細的解釋:http://blog.csdn.net/bluishglc/article/details/7596118 簡單來說就是spring在啟動時會載入xsd檔案,它首先會到本地查詢xsd檔案(一般都會包含在spring的jar包中),如果找不到則會到xml頭部定義的url指定路徑下中去尋找xsd,如果找不到則會報錯。

附:在spring jar包下的META-INF資料夾中都會包含一個spring.schemas檔案,其中就包含了對xsd檔案的路徑定義,具體如下圖所示:

spring-aop.jar包下META-INF資料夾下的內容

圖:spring-aop.jar包下META-INF資料夾下的內容

spring.schemas檔案內容

圖:spring.schemas檔案內容

由於我的工程是在內網,所以通過url路徑去尋找肯定是找不到的,但是比較奇怪的是既然spring的jar包中都會包含,那為什麼還是找不到呢?

該bug產生的原因如下:工程一般依賴了很多的jar包,而被依賴的jar又會依賴其他的jar包,這樣,當工程中依賴到不同的版本的spring時,在使用assembly進行打包時,只能將某一個版本jar包下的spring.schemas檔案放入最終打出的jar包裡,這就有可能遺漏了一些版本的xsd的本地對映,所以會報錯。

所以一般推薦使用另外的一個外掛來進行打包,外掛名稱為:maven-shade-plugin,shade外掛打包時在對spring.schemas檔案處理上,它能夠將所有jar裡的spring.schemas檔案進行合併,在最終生成的單一jar包裡,spring.schemas包含了所有出現過的版本的集合,要使用shade外掛,必須在pom進行如下配置:

Xml程式碼  收藏程式碼
  1. <plugin>  
  2.     <groupId>org.apache.maven.plugins</groupId>  
  3.     <artifactId>maven-shade-plugin</artifactId>  
  4.     <version>1.4</version>  
  5.     <executions>  
  6.         <execution>  
  7.             <phase>package</phase>  
  8.             <goals>  
  9.                 <goal>shade</goal>  
  10.             </goals>  
  11.             <configuration>  
  12.                 <transformers>  
  13.                     <transformer  
  14.                         implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">  
  15.                         <resource>META-INF/spring.handlers</resource>  
  16.                     </transformer>  
  17.                     <transformer  
  18.                         implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">  
  19.                         <mainClass>com.chenzhou.examples.Main</mainClass>  
  20.                     </transformer>  
  21.                     <transformer  
  22.                         implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">  
  23.                         <resource>META-INF/spring.schemas</resource>  
  24.                     </transformer>  
  25.                 </transformers>  
  26.             </configuration>  
  27.         </execution>  
  28.     </executions>  
  29. </plugin>  

上面配置檔案中有一段定義:

Xml程式碼  收藏程式碼
  1. <transformer  
  2.     implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">  
  3.     <resource>META-INF/spring.schemas</resource>  
  4. </transformer>  

 上面這段配置意思是把spring.handlers和spring.schemas檔案以append方式加入到構建的jar包中,這樣就不會存在出現xsd找不到的情況。

配置完pom後,呼叫mvn clean install命令進行構建,構建成功後開啟工程target目錄,發現生成了2個jar包,一個為:original-XXX-0.0.1-SNAPSHOT.jar,另一個為:XXX-0.0.1-SNAPSHOT.jar,其中original...jar裡只包含了工程自己的class檔案,而另外的一個jar包則包含了工程本身以及所有依賴的jar包的class檔案。我們只需要使用第二個jar包就可以了。

參考資料: