Java_java動態編譯整個項目,解決jar包找不到問題


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###

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM