maven-shade-plugin 使用maven外掛對java工程進行打包
現在基本上都是採用maven來進行開發管理,我有一個需求是需要把通過maven管理的java工程打成可執行的jar包,這樣也就是說必需把工程依賴的jar包也一起打包。而使用maven預設的package命令構建的jar包中只包括了工程自身的class檔案,並沒有包括依賴的jar包。我們可以通過配置外掛來對工程進行打包,pom具體配置如下:
maven-assembly-plugin
Xml程式碼- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
-
<configuration
- <appendAssemblyId>false</appendAssemblyId>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- <archive>
- <manifest>
-
<mainClass
- </manifest>
- </archive>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
- <phase>package</phase>
-
<
- <goal>assembly</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
其中<mainClass></mainClass>的值表示此工程的入口類,也就是包含main方法的類,在我的例子中就是com.chenzhou.examples.Main。配置完pom後可以通過執行mvn assembly:assembly命令來啟動外掛進行構建。構建成功後會生成jar包,這樣我們就可以在命令列中通過java -jar XXX.jar來執行jar件了。
不過使用此外掛會有一些問題:我在工程中依賴了spring框架的jar包,我打包成功後使用命令來呼叫jar包時報錯如下(內網環境):
Shell程式碼- 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.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程式碼- <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.AppendingTransformer">
- <resource>META-INF/spring.handlers</resource>
- </transformer>
- <transformer
- implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
- <mainClass>com.chenzhou.examples.Main</mainClass>
- </transformer>
- <transformer
- implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
- <resource>META-INF/spring.schemas</resource>
- </transformer>
- </transformers>
- </configuration>
- </execution>
- </executions>
- </plugin>
上面配置檔案中有一段定義:
Xml程式碼- <transformer
- implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
- <resource>META-INF/spring.schemas</resource>
- </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包就可以了。
參考資料: