最近在做的課程網站需要實現將學生的源代碼提交,並對學生間的程序進行比賽、排名。
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/