本文將介紹,如何將 Spring 應用如何打包爲可執行的 jar ,以及在打包、執行 jar 中遇到的問題和解決方案。
場景:
現有一需求,需要把通過 Spring + MyBatis + Maven 構建的非 Web 應用,打包爲一個 jar 包,提供給線上通過 java 命令來執行。
問題及解決方案
1. 打包插件的選擇
正常方式搭建、開發 Spring、MyBatis 等相關代碼和依賴。構建完成後,重點注意 pom.xml 文件中 build 標籤內的插件。
使用含 bug 的 maven-assembly-plugin
assembly 插件在通過 mvn clean package 打包完成後,運行jar包文件,由於在公司內網,會報一些 spring.xml 文件內,**.xsd 文件找不到的問題,如
通配符的匹配很全面, 但無法找到元素 ‘context:component-scan’ 的聲明 同類型的錯誤。
關於 ** .xsd 文件的加載細節,可以參考這篇文章的介紹。
當我們發現 jar 包在執行時,**.xml 拋出一些 **.xsd 文件找不到的錯誤時,可以打開 jar 包,./META-INF/spring.schemas 文件中查看,是否含有需要的 xsd 文件及對應的文件。
推薦使用 maven-shade-plugin 打包
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</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.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.xxx.MainClass</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
配置完 pom 後,調用 mvn clean install 命令進行構建,所有的 **.xsd 文件都會被打包,並以 key-value 的形式,記錄在 ./META-INF/spring.schemas 文件中。所有的 **.xsd 文件都在這個文件裏記錄了存儲路徑,如果沒有,應用將會通過網絡地址去查找,如果還是查找不到,就會拋出對應的錯誤。
構建成功後 target 目錄,生成2個jar包,一個爲:original-XXX-0.0.1-SNAPSHOT.jar,另一個爲:XXX-0.0.1-SNAPSHOT.jar。其中 original…jar裏只包含了工程自己的class文件,而另外的一個jar包則包含了工程本身以及所有依賴的jar包的class文件。
我們只需要使用第二個jar包就可以了。
2. jar 包內配置文件訪問的問題
jar包內的配置文件,已經不能使用 new File(“filePath”) 方式來尋找了,因爲文件路徑已經變成 ** .jar!/ **,這種格式並不是文件資源定位符的格式。
如果需要讓 jar 中的代碼讀取到自己的資源文件,可以通過 YourClassName.class.getResourceAsStream("/abc.conf"); 方法來獲取到文件的輸入流,進而獲取到文件內容。