有些時候,須要經過DOS批處理來編譯整個項目的JAVA文件;而且編譯後還要對Class文件進行打包成jar文件。。。
這還不是最煩的,最煩的是,編譯和打包的時候須要依賴其餘多個jar文件,困難就這麼來了。。。。java
項目結構
App
|-dest
| |-libs(copy過來的依賴庫)
| |-bin(生成的class文件)
|
|-libs(依賴庫)
|-src(須要編譯的JAVA源文件)windows
若是須要對項目編譯,首先,須要清理dest文件夾bash
REM 刪除dest包
IF EXIST dest RMDIR /s /q destapp
REM 建立 dest/libs和dest/bin文件夾
mkdir "dest/libs"
mkdir "dest/bin"編碼
REM copy依賴庫
copy libs\*.jar dest\libs\ /yspa
而後,從JAVA的編譯命令用法入手:
javac <選項> <源文件>
其參數中,"-d <目錄>",指定存放生成的類文件的位置
"-cp <路徑>",指定查找用戶類文件和註釋處理程序的位置(我的理解就是所須要依賴的jar包)
"-encoding <編碼>", 指定源文件使用的字符編碼(咱們使用UTF-8)
例如: javac -d dest\bin -cp libs\commons-logging-1.1.1.jar;freemarker-2.3.19.jar; -encoding UTF-8 src/a.java src/com.mycls/b.java src/com.mycls/c.java
上面Demo是加載其依賴庫並使用UTF-8編碼編譯指定java文件code
繼續,對編譯好的class文件進行打成jar包orm
REM 須要在class的根目錄打包
cd dest/binblog
REM 將當前目錄下全部文件打包到上級目錄的myjar.jar文件中
jar -cvf ../myjar.jar *
固然了,還能夠經過對MANIFEST.MF的定製來指定默認運行的類utf-8
上面的內容,對於一個JAVA開發來講都不是事兒,接下來問題來了。。。。
在編譯的時候,javac加載依賴庫是指定的依賴庫,那若是有不少依賴庫,而且在開發過成功還會發生變更呢?難道要修改cmd(bat)批處理?
這個時候,就須要指定一個libs目錄,加載此目錄下的全部文件便可。但是怎麼拼接這個參數呢?
以下所示(若是沒有依賴的jar,可將cp相關部分去除):
SETLOCAL enableDelayedExpansion
FOR %%i IN ("libs\*.jar") DO SET CP=%%i;!CP!
SET OPT=-d %OUTPUT_PATH%\bin -cp %CP% -encoding utf-8
EndLocal
這樣,全部的參數就造成了,
SETLOCAL enableDelayedExpansion是擴展本地環境變量延遲,是獲取CP參數的一個出錯點,若是沒有這個,for裏面的賦值語句是無效的。
OUTPUT_PATH 變量是指定編譯後的class文件的位置,
CP 變量就是全部須要加載用的lib包
同理,循環src目錄下的全部文件和目錄並拼接全部的java文件(配置文件請自行處理),能夠獲取全部的java文件:
CD %SRC_PATH%
FOR /R %%b IN ( . ) DO (
IF EXIST %%b/*.java SET JFILES=!JFILES! %%b/*.java
)
CD ..
REM 正在編譯...
javac %OPT% %JFILES%
REM 編譯結束
而後就是打包了,
CD %OUTPUT_PATH%\bin
REM 將全部文件打包爲mylib.jar並存放到父目錄
jar -cvf ../mylib.jar *
REM 打包完畢
對於SHELL命令來講,這樣的批處理更爲簡單:
#獲取全部的依賴lib
export libs=`find libs -name "*.jar" |xargs|sed "s/ /:/g"`
#獲取全部須要編譯的java文件
export jfiles=`find src -name "*.java" |xargs|sed "s/ / /g"`
#準備編譯
opt="-d $OUTPUT_PATH/bin -cp ${libs} -encoding utf-8"
javac $opt ${jfiles}
#打包
cd ${OUTPUT_PATH}/bin
jar -cvf ${CUR}/dest/mylib.jar *
cd ${CUR}/src
jar -cvf ${CUR}/dest/mylib-source.jar *
如下圖目錄結構爲例:
裏面的compile.sh和compile.cmd文件的內容分別爲:
調用腳本的JAVA代碼:
1 package test.compile; 2 3 import java.io.File; 4 import java.text.SimpleDateFormat; 5 6 /** 7 * <p>編譯abc目錄下全部java文件</p> 8 * @author Ares 9 * @version $Id: CompileTool.java, v 0.1 2015年02月26日 上午10:41:32 Exp $ 10 */ 11 public class CompileTool { 12 13 // DOS: 第一個參數是 src、cmd的父目錄,第二個參數爲最終壓縮包(mylib.jar,mylib-source.jar的目錄)所在目錄 14 15 private static String os_name = System.getProperty("os.name").toLowerCase(); 16 17 public static boolean compileAndJar(final String jarRootPath) throws Exception{ 18 String app_path = jarRootPath; // app_path是指定abc的絕對路徑,由於java文件執行目錄可能跟編譯目錄不一致,因此若是須要請使用此參數(腳本中第一步須要進入此目錄) 19 if(app_path !=null && (!app_path.endsWith("/") && !app_path.endsWith(File.separator))) 20 app_path += File.separator; 21 String compile_datetime = new SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date()); 22 // 無後綴的jar名稱(cmd 會拼寫爲 jarname.jar 和 jarname-source.jar) 23 String jar_name = "myjar_" + compile_datetime; // jar名稱格式,mylib_日期時間,以參數的形式傳入,下面的腳本中未使用,如若使用,請替代腳本中的mylib 24 String cmd = ""; 25 java.io.File cmdFile = null; 26 if(os_name.indexOf("windows") > -1){ 27 cmd = "cmd.exe /C start " + app_path + "compile.exe " + app_path + " " + jar_name; 28 cmdFile = new java.io.File(app_path + "compile.exe"); 29 }else { 30 cmd = app_path + "compile.sh " + app_path + " " + jar_name; 31 cmdFile = new java.io.File(app_path + "compile.sh"); 32 } 33 if(!cmd.equals("") && cmdFile != null && cmdFile.exists()){ 34 if(!cmdFile.canExecute()) cmdFile.setExecutable(true); 35 return callCmd(cmd); 36 }else { 37 throw new Exception("can't find compile command. command:"+cmdFile.getAbsolutePath()); 38 } 39 } 40 41 private static boolean callCmd(String cmdStr) { 42 try { 43 Process child = Runtime.getRuntime().exec(cmdStr); 44 java.io.InputStream in = child.getInputStream(); 45 while (in.read() != -1) {} 46 in.close(); 47 try { 48 child.waitFor(); 49 return true; 50 } catch (InterruptedException e) { 51 e.printStackTrace(); 52 } 53 return false; 54 } catch (java.io.IOException e) { 55 e.printStackTrace(); 56 } 57 return false; 58 } 59 }
下面是compile.sh文件內容:
#!/bin/bash CUR=$(pwd) ## reset dest folder OUTPUT_PATH=${CUR}/dest rm -rf $OUTPUT_PATH mkdir -p ${OUTPUT_PATH}/bin mkdir -p ${OUTPUT_PATH}/libs ## 獲取依賴庫和須要編譯的java文件 export libs=`find libs -name "*.jar" |xargs|sed "s/ /:/g"` export jfiles=`find src -name "*.java" |xargs|sed "s/ / /g"` ## 編譯 opt="-d $OUTPUT_PATH/bin -cp ${libs} -encoding utf-8" javac $opt ${jfiles} ## 打包 cd ${OUTPUT_PATH}/bin jar -cvf ${CUR}/dest/mylib.jar * cd ${CUR}/src jar -cvf ${CUR}/dest/mylib-source.jar *
下面是compile.cmd文件內容:
1 @ECHO OFF 2 SETLOCAL enableDelayedExpansion 3 4 REM Save Current Path(保存當前路徑) 5 SET CUR=%CD% 6 7 REM Dir Structure(設置目錄結構) 8 SET OUTPUT_PATH=dest 9 SET SRC_PATH=%CUR%\src 10 SET LIBS_PATH=%CUR%\libs 11 12 REM Reset Output Dir(重置清空輸出目錄) 13 IF EXIST %OUTPUT_PATH% RMDIR /s /q %OUTPUT_PATH% 14 IF NOT EXIST %OUTPUT_PATH% MKDIR %OUTPUT_PATH% 15 CD %OUTPUT_PATH% 16 IF NOT EXIST bin MKDIR bin 17 IF NOT EXIST libs MKDIR libs 18 19 REM Copy Files(複製jar文件) 20 CD %CUR% 21 SET CP=%OUTPUT_PATH%/libs 22 copy %LIBS_PATH%\*.jar %OUTPUT_PATH%\libs\ /y 23 24 CD %CUR% 25 FOR %%i IN ("libs\*.jar") DO SET CP=%%i;!CP! 26 SET OPT=-d %OUTPUT_PATH%\bin -cp %CP% -encoding utf-8 27 28 CD %SRC_PATH% 29 REM 獲取全部須要編譯的java源文件,並用空格連接 30 REM 此處須要開啓變量延遲(SETLOCAL enableDelayedExpansion不可缺乏) 31 32 FOR /R %%b IN ( . ) DO ( 33 IF EXIST %%b/*.java SET JFILES=!JFILES! %%b/*.java 34 ) 35 36 CD %CUR% 37 REM 正在編譯... 38 javac %OPT% %JFILES% 39 40 IF "%errorlevel%" EQU "0" ( 41 ECHO 編譯成功,正在拷貝資源文件... 42 copy %CUR%/src/*.* %OUTPUT_PATH%\src\ /y 43 ) 44 45 REM 準備打包編譯文件和JAVA源文件 46 CD %OUTPUT_PATH%/bin 47 jar -cvf ../mylib.jar * 48 cd %SRC_PATH% 49 jar -cvf %CUR%/dest/mylib-source.jar * 50 51 EndLocal 52 exit