最近在做的课程网站需要实现将学生的源代码提交,并对学生间的程序进行比赛、排名。
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/