使用 maven 外掛 maven-shade-plugin 對可執行 java 工程及其全部依賴 jar 進行打包
現在基本上都是採用 maven 來進行開發管理,我有一個需求是需要把通過 maven 管理的 java 工程打成可執行的 jar 包,這樣也就是說必需把工程依賴的 jar 包也一起打包。而使用 maven 預設的 package 命令構建的 jar 包中只包括了工程自身的 class 檔案,並沒有包括依賴的 jar 包。我們可以通過配置外掛來對工程進行打包,pom 具體配置如下:
maven-assembly-plugin (使用此外掛會有一些問題)
Xml程式碼- <plugin>
-
<artifactId>maven-assembly-plugin</
- <configuration>
- <appendAssemblyId>false</appendAssemblyId>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- <archive>
-
<manifest
- <mainClass>com.chenzhou.examples.Main</mainClass>
- </manifest>
- </archive>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
-
<phase>package</
- <goals>
- <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>
上面配置檔案中有一段定義:
- <transformer
- implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
- <resource>META-INF/spring.handlers</resource>
- </transformer>
- <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 包就可以了。
參考資料: