java動態編譯整個項目,解決jar包找不到問題
原文:http://itzyx.com/index.php/javac/
動態將java文件編譯為class文件解決方案:
將temp\sdl\src目錄中的java源文件編譯成class文件,並存放到temp\sdl\classes目錄中
java中早就提供了用java方式去動態編譯java源文件的接口,有關java動態編譯的API都在javax.tools包中。使用jdk1.6以上版本提供的JavaCompiler工具來動態編譯java源文件。
我們可以通過ToolProvider類的靜態方法getSystemJavaCompiler得到JavaCompiler對象實例。
// 獲取編譯器實例
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
得到JavaCompiler對象實例后,我們可以調用該工具的getTask(Writer out, JavaFileManager fileManager, DiagnosticListener<? super JavaFileObject> diagnosticListener, Iterable<String> options, Iterable<String> classes, Iterable<? extends JavaFileObject> compilationUnits) 方法獲取一個編譯任務對象。
CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
該方法的第一個參數為文件輸出,這里我們可以不指定,我們采用javac命令的-d參數來指定class文件的生成目錄。
第二個參數為文件管理器實例
// 獲取標准文件管理器實例 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
該文件管理器實例的作用就是將我們需要動態編譯的java源文件轉換為getTask需要的編譯單元。
// 獲取要編譯的編譯單元 Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);
第三個參數DiagnosticCollector<JavaFileObject> diagnostics是在編譯出錯時,存放編譯錯誤信息。
第四個參數為編譯命令選項,就是javac命令的可選項,這里我們主要使用了-d和-sourcepath這兩個選項。
/** * 編譯選項,在編譯java文件時,編譯程序會自動的去尋找java文件引用的其他的java源文件或者class。 -sourcepath選項就是定義java源文件的查找目錄, -classpath選項就是定義class文件的查找目錄,-d就是編譯文件的輸出目錄。 */ Iterable<String> options =Arrays.asList("-encoding",encoding,"-classpath",jars,"-d", targetDir, "-sourcepath", sourceDir);
第五個參數為類名稱
第六個參數為上面提到的編譯單元,就是我們需要編譯的java源文件
當我們得到CompilationTask compilationTask編譯任務后,我們就可以調用compilationTask.call()方法進行編譯工作
// 運行編譯任務 compilationTask.call()
package com.lkb.autoCode.util; import javax.tools.*; import javax.tools.JavaCompiler.CompilationTask; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class DynamicCompilerUtil { private String jars = ""; private String targetDir = ""; /** * 判斷字符串是否為空 有值為true 空為:false */ public boolean isnull(String str) { if (null == str) { return false; } else if ("".equals(str)) { return false; } else if (str.equals("null")) { return false; } else { return true; } } /** * 編譯java文件 * * @param encoding 編譯編碼 * @param jars 需要加載的jar * @param filePath 文件或者目錄(若為目錄,自動遞歸編譯) * @param sourceDir java源文件存放目錄 * @param targetDir 編譯后class類文件存放目錄 * @param diagnostics 存放編譯過程中的錯誤信息 * @return * @throws Exception */ public boolean compiler(String encoding, String jars, String filePath, String sourceDir, String targetDir, DiagnosticCollector<JavaFileObject> diagnostics) throws Exception { // 獲取編譯器實例 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); // 獲取標准文件管理器實例 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); try { if (!isnull(filePath) && !isnull(sourceDir) && !isnull(targetDir)) { return false; } // 得到filePath目錄下的所有java源文件 File sourceFile = new File(filePath); List<File> sourceFileList = new ArrayList<File>(); this.targetDir = targetDir; getSourceFiles(sourceFile, sourceFileList); // 沒有java文件,直接返回 if (sourceFileList.size() == 0) { System.out.println(filePath + "目錄下查找不到任何java文件"); return false; } // 獲取要編譯的編譯單元 Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList); /** * 編譯選項,在編譯java文件時,編譯程序會自動的去尋找java文件引用的其他的java源文件或者class。 -sourcepath選項就是定義java源文件的查找目錄, -classpath選項就是定義class文件的查找目錄。 */ Iterable<String> options = Arrays.asList("-encoding", encoding, "-classpath", jars, "-d", targetDir, "-sourcepath", sourceDir); CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits); // 運行編譯任務 return compilationTask.call(); } finally { fileManager.close(); } } /** * 查找該目錄下的所有的java文件 * * @param sourceFile * @param sourceFileList * @throws Exception */ private void getSourceFiles(File sourceFile, List<File> sourceFileList) throws Exception { if (sourceFile.exists() && sourceFileList != null) {//文件或者目錄必須存在 if (sourceFile.isDirectory()) {// 若file對象為目錄 // 得到該目錄下以.java結尾的文件或者目錄 File[] childrenFiles = sourceFile.listFiles(new FileFilter() { public boolean accept(File pathname) { if (pathname.isDirectory()) { try { new CopyDirectory().copyDirectiory(pathname.getPath(), targetDir + pathname.getPath().substring(pathname.getPath().indexOf("src") + 3, pathname.getPath().length())); } catch (IOException e) { e.printStackTrace(); } return true; } else { String name = pathname.getName(); if (name.endsWith(".java") ? true : false) { return true; } try { new CopyDirectory().copyFile(pathname, new File(targetDir + pathname.getPath().substring(pathname.getPath().indexOf("src") + 3, pathname.getPath().length()))); } catch (IOException e) { e.printStackTrace(); } return false; } } }); // 遞歸調用 for (File childFile : childrenFiles) { getSourceFiles(childFile, sourceFileList); } } else {// 若file對象為文件 sourceFileList.add(sourceFile); } } } /** * 查找該目錄下的所有的jar文件 * * @param jarPath * @throws Exception */ private String getJarFiles(String jarPath) throws Exception { File sourceFile = new File(jarPath); // String jars=""; if (sourceFile.exists()) {// 文件或者目錄必須存在 if (sourceFile.isDirectory()) {// 若file對象為目錄 // 得到該目錄下以.java結尾的文件或者目錄 File[] childrenFiles = sourceFile.listFiles(new FileFilter() { public boolean accept(File pathname) { if (pathname.isDirectory()) { return true; } else { String name = pathname.getName(); if (name.endsWith(".jar") ? true : false) { jars = jars + pathname.getPath() + ";"; return true; } return false; } } }); } } return jars; } public static void main(String[] args) { try { // 編譯F:\\亞信工作\\SDL文件\\sdl\\src目錄下的所有java文件 String filePath = "E:\\workspace\\COD-MS\\src"; String sourceDir = "E:\\workspace\\COD-MS\\src"; String jarPath = "E:\\workspace\\COD-MS\\WebRoot\\WEB-INF\\lib"; String targetDir = "E:\\java\\project\\bin"; DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); DynamicCompilerUtil dynamicCompilerUtil = new DynamicCompilerUtil(); boolean compilerResult = dynamicCompilerUtil.compiler("UTF-8", dynamicCompilerUtil.getJarFiles(jarPath), filePath, sourceDir, targetDir, diagnostics); if (compilerResult) { System.out.println("編譯成功"); } else { System.out.println("編譯失敗"); for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { // System.out.format("%s[line %d column %d]-->%s%n", diagnostic.getKind(), diagnostic.getLineNumber(), // diagnostic.getColumnNumber(), // diagnostic.getMessage(null)); System.out.println(diagnostic.getMessage(null)); } } } catch (Exception e) { e.printStackTrace(); } } }
package com.lkb.autoCode.util; import java.io.*; /** * 復制文件夾或文件夾 */ public class CopyDirectory { // 源文件夾 String url1 = "E:\\workspace\\DeployeTest"; // 目標文件夾 String url2 = "E:\\java\\project\\bin"; public static void main(String args[]) throws IOException { CopyDirectory copyDirectory = new CopyDirectory(); // 創建目標文件夾 (new File(copyDirectory.url2)).mkdirs(); // 獲取源文件夾當前下的文件或目錄 File[] file = (new File(copyDirectory.url1)).listFiles(); for (int i = 0; i < file.length; i++) { if (file[i].isFile()) { // 復制文件 copyDirectory.copyFile(file[i], new File(copyDirectory.url2 + file[i].getName())); } if (file[i].isDirectory()) { // 復制目錄 String sourceDir = copyDirectory.url1 + File.separator + file[i].getName(); String targetDir = copyDirectory.url2 + File.separator + file[i].getName(); copyDirectory.copyDirectiory(sourceDir, targetDir); } } } /** * 復制文件 * * @param sourceFile 源文件 * @param targetFile 目標文件 * @throws IOException */ public void copyFile(File sourceFile, File targetFile) throws IOException { // 新建文件輸入流並對它進行緩沖 FileInputStream input = new FileInputStream(sourceFile); BufferedInputStream inBuff = new BufferedInputStream(input); // 新建文件輸出流並對它進行緩沖 FileOutputStream output = new FileOutputStream(targetFile); BufferedOutputStream outBuff = new BufferedOutputStream(output); // 緩沖數組 byte[] b = new byte[1024 * 5]; int len; while ((len = inBuff.read(b)) != -1) { outBuff.write(b, 0, len); } // 刷新此緩沖的輸出流 outBuff.flush(); // 關閉流 inBuff.close(); outBuff.close(); output.close(); input.close(); } /** * 復制文件夾 * * @param sourceDir 源文件夾路徑 * @param targetDir 目標文件夾路徑 * @throws IOException */ public void copyDirectiory(String sourceDir, String targetDir) throws IOException { // 新建目標目錄 (new File(targetDir)).mkdirs(); // 獲取源文件夾當前下的文件或目錄 File[] file = (new File(sourceDir)).listFiles(); for (int i = 0; i < file.length; i++) { if (file[i].isFile()) { // 源文件 File sourceFile = file[i]; // 目標文件 File targetFile = new File(new File(targetDir) .getAbsolutePath() + File.separator + file[i].getName()); copyFile(sourceFile, targetFile); } if (file[i].isDirectory()) { // 准備復制的源文件夾 String dir1 = sourceDir + "/" + file[i].getName(); // 准備復制的目標文件夾 String dir2 = targetDir + "/" + file[i].getName(); copyDirectiory(dir1, dir2); } } } }
摘自百度文庫:http://wenku.baidu.com/link?url=hFsuio_UxS4_vkt7ov8grKZp40rxJ8AR_ktzhNReoG4MGXFKf-dP_wVodVsErD737eKvaaNhVY9yEBdyXG1IEgiZeukpGU93pxCBTIbXvq3###