web項目實現類文件上傳、編譯及加載

最近在做的課程網站需要實現將學生的源代碼提交,並對學生間的程序進行比賽、排名。

1 網站頁面源代碼的提交

首先實現網站頁面源代碼的提交(文件夾下的多文件提交),拷貝至後臺相應的文件夾下

前端代碼(表單提交):

<div class="col-md-2 title">提交棋手</div>
<div class="col-md-4 data text">
   <input type="file" id="fileFolder" name="fileFolder" webkitdirectory mozdirectory >
</div>

後端代碼:

for(MultipartFile f:files) {
     File file1;
     String name = "";
     try {
         if (f instanceof CommonsMultipartFile) {
             //轉換成這個對象,然後我們需要通過裏面的FileItem來獲得相對路徑
             CommonsMultipartFile f2 = (CommonsMultipartFile) f;
             name = f2.getFileItem().getName();
             file1 = new File(path + "/" + name);
             file1.mkdirs();
             file1.createNewFile();
             f.transferTo(file1);
          }
      } catch (Exception e) {
           e.printStackTrace();
      }
}

2 編譯提交的java源代碼

源代碼放在相應位置後,就需要調用命令行對提交的代碼進行編譯,並將文件放到classes文件夾

public static void executeCmd(ArrayList<String> fileList, ArrayList<String> classList) {
        try {
            //把文件夾下所有java文件完整路徑存到files數組中,不用考慮引用關係
            String classPath="E:\\program\\course_website\\jago\\target\\classes";
            //class文件存放路徑

            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
            Iterable<? extends JavaFileObject> javaFileObjects =
            manager.getJavaFileObjectsFromStrings(fileList);
            //options就是指定編譯輸入目錄,與我們命令行寫javac -d C://是一樣的
            List<String> options = new ArrayList<String>();
            options.add("-classpath");
            options.add(classPath);
            options.add("-d");
            options.add(classPath);
            JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, options, null, javaFileObjects);
            boolean compileFlag = task.call();
            manager.close();  
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

3 類加載

       將代碼編譯完成後就需要將class加載進jvm中,剛開始我寫了一個自定義的classLoader,繼承ClassLoader,但在web項目運行後出現了java.lang.ClassCastException的java類型轉換異常,但類型確實是可以轉換的,不應該出現這樣的問題,百度後發現是因爲類加載器的不同所以導致了類型轉換失敗。tomcat 擁有不同的自定義類加載器,通過getClassLoader()方法發現強轉的類加載器是ParallelWebappClassLoader,那麼我們剛剛編譯後的class文件也通過此加載器加載就不會出現類型強轉錯誤了。

public class MyClassLoader extends URLClassLoader {
    //該路徑是classpath路徑
    public static File file = new File("E:\\program\\course_website\\jago\\target\\classes");

    //MyClassLoader從上面的classpath路徑加載類
    public MyClassLoader() throws Exception {
        super(new URL[] {file.toURL()}, null, null);
    }
    public MyClassLoader(ClassLoader parent) throws Exception {
        super(new URL[] {file.toURL()}, parent);
    }
}

這裏需要指出 JVM中確定一個類型的座標是通過類加載器和全類名做到的 。

在JVM中,如何確定一個類型實例?答:全類名嗎?不是,是類加載器加上全類名。在JVM中,類型被定義在一個叫SystemDictionary 的數據結構中,該數據結構接受類加載器和全類名作爲參數,返回類型實例。

     SystemDictionary 如圖所示:

      類型加載時,需要傳入類加載器和需要加載的全類名,如果在 SystemDictionary 中能夠命中一條記錄,則返回class 列上對應的類型實例引用,如果無法命中記錄,則會調用loader.loadClass(name);進行類型加載。

      想要了解ClassLoader的內容可以看一下這篇博客:https://blog.csdn.net/liangxw1/article/details/51353572/

發佈了18 篇原創文章 · 獲贊 7 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章