背景
由於版權問題,maven中央倉庫缺少oracle jdbc的驅動,這個給開發帶來了很多不便利性。也出現各種各樣的解決方案,基本就兩種思路:
- 將oracle驅動安裝到本地倉庫,這個需要大家統一好名稱和版本
- 使用第三方倉庫
不管哪種方案,本來maven就是為了方便開發人員管理包依賴,這樣一來反而更麻煩。當然,不是maven的錯,oracle這事做的確實夠sb。(聽說oracle要對java進行收費???)
那麼有沒有更好的方案,假設你現在開發了一個框架,框架支援多資料庫,並且已經將jar包提交至maven中央倉庫,如果你的jar包裡面就已經包含了oracle驅動,那麼使用框架的人就不用額外再去匯入驅動。
這種方案有以下幾個小問題
- 會不會有版權問題(這個不是很瞭解)
- 驅動升級怎麼辦
- 怎麼把驅動打到jar包裡
關於驅動升級問題,可以對jar包釋出多個版本,比如純淨版不包含驅動,驅動xxx版包含不同版本的驅動。
本文主要探討的就是第三個問題,怎麼把驅動打到jar包裡
背景交代完畢,正文開始。
實現
遇到的問題
你可能覺得,這是個很簡單的事,通過idea的Artifacts
不就行了。是的,如果你只是想在本地打一個jar包,這種方式簡單方便。但如果要上傳到maven,就得使用maven來打包,maven是不管你ide是怎麼配置的,而且maven不會將依賴包打到jar包裡的。有幾個方案可以考慮
- 藉助maven外掛maven-assembly-plugin可以實現自定義打包,但是該外掛是將依賴包全部放在
lib
目錄下,這個不是我的本意,我的本意是將依賴包裡的class檔案解壓到根目錄下,和自開發的jar包同一個目錄下。(這個外掛我研究了很久不能實現就放棄了,如果有知道怎麼實現的讀者歡迎留言) - 自己寫外掛實現,其實難度也不大,就是麻煩點
- 藉助maven指令碼執行外掛exec-maven-plugin執行自定義指令碼對maven打包後的jar包進行”改造”。
最終選擇了第三個方案,寫shell指令碼實現自定義打包
配置
首先引入外掛的依賴
pom.xml
<build>
<plugins>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<executions>
<execution>
<id>asan</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${basedir}/scripts/package.sh</executable>
<arguments>
<argument>${project.build.directory}</argument>
<argument>${project.build.finalName}</argument>
<argument>/Users/asan/u01/docker/lib/ojdbc6.jar</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
- phase:在打包這個生命週期結束後執行該指令碼
- executable:指令碼目錄位置
- arguments:傳給指令碼的引數,這裡傳了三個引數
- ${basedir}:當前目錄,就是專案所在目錄
- ${project.build.directory}:maven構建目錄,就是
target
目錄 - ${project.build.finalName}:maven打包名稱
- /you/path/ojdbc6.jar:要打進去的jar包路徑
指令碼
package.sh
v_workspace=$1/tmp
v_name=$2.jar
v_depency=$3
v_depency_name=`basename $3`
echo "workspace==>$v_workspace"
echo "name==>$v_name"
echo $v_depency
echo $v_depency_name
rm -rf $v_workspace
mkdir -p $v_workspace
cp $v_depency $v_workspace
cd $v_workspace
jar -xf $v_workspace/$v_depency_name
rm -rf $v_workspace/$v_depency_name
rm -rf META-INF/
cp $1/$v_name $v_workspace
for file in `ls $v_workspace`
do
if [ -d $file ]
then
jar -uf $v_workspace/$v_name $file
fi
done
rm -rf $1/$v_name
mv $v_workspace/$v_name $1/$v_name
整個指令碼的大概流程如下
- 建立一個臨時目錄
v_workspace
- 將依賴包複製到臨時目錄下
- 解壓依賴包
- 刪除jar包和META-INF資料夾
- 將專案的jar包複製到臨時目錄下
- 遍歷所有資料夾,將資料夾通過命令
jar -uf
更新到專案jar包裡 - 用新的jar包替換掉老的jar包
寫在最後
現在指令碼里只支援一個jar包,稍微修改下就可以支援多個,或者你可以在自己本地把多個jar包用jar -uf
打到一個jar包裡,再執行指令碼。