前言
这几天刚好了解了一部分类加载器的知识,与此同时博主又想来大三那年老师留下的作业,自己写一个做题网站,当时一点思路没有,但咱已不是当年的自己了
这灵感像吃了泻药一样,一泻千里,接下来说一下思路和实现。
小知识
类加载器
众所周知,类加载器有启动器类加载器,扩展器类加载器以及自定义类加载器,他们分管不同的区域,具体的知识,该文章就不进行赘述了,以后会整理一篇详细的类加载知识。
这里我们只需要知道,类加载器就是将java文件加载到我们的jvm中,从而我们可以采用反射方式对其进行操作
本文就是采用自定义的类加载器来加载我们外部的java文件
Process
process就是为了实现发起一个进程,主要作用就是将我们生成的java文件转换为class文件,然后再由类加载器将class文件加载
具体实现
文本生成java文件
这里采用的是将h5的textarea的内容传递给接口,由后端接口直接把内容导入到java文件中
主要代码
文件工具类
这里就是实现文本写入到文件中
bufferedWriter=new BufferedWriter(new FileWriter("D://java//xiaow.java"));
bufferedWriter.write(info);
bufferedWriter.close();
将java文件编译为class文件
需要采用process发起一个进程,并且执行命令生成class文件,命令如下
javac **.java
主要代码
java文件编译为class文件
public static void execCmd(String cmd) throws Exception {
Process process = null;
try {
// 执行命令, 返回一个子进程对象(命令在子进程中执行)
process = Runtime.getRuntime().exec(cmd, null);
// 方法阻塞, 等待命令执行完成(成功会返回0)
process.waitFor();
} finally {
// 销毁子进程
if (process != null) {
process.destroy();
}
}
}
自定义类加载器导入class文件
主要代码
这里采用是自定义的类加载器,定义如下
public class MyClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
//存放class文件的位置
String path = "D:\\java\\" + name + ".class";
ByteArrayOutputStream out=new ByteArrayOutputStream();
//复制文件到out输出流中
Files.copy(Paths.get(path),out);
byte[] bytes = out.toByteArray();
//由byte数组生成Class
Class<?> aClass = defineClass(name, bytes, 0, bytes.length);
return aClass;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//方便外部调用
public Class<?> findclass(String name) throws ClassNotFoundException {
Class<?> findclass = findClass(name);
return findclass;
}
}
接口代码
这里还是采用还是controller来编写接口,从而实现对上传程序的测试
主要代码
@RestController
@RequestMapping("/code")
public class CodeController {
//测试数据集
//博主采用写死的方式,有兴趣的可以在数据库中拿取
private static Map<Integer,Integer> map=new HashMap<>();
static {
map.put(1,1);
map.put(2,4);
map.put(3,9);
map.put(4,16);
map.put(5,25);
}
/**
*
* @param java 运行代码,把包信息去掉
* @param methodName 调用的方法名称
* @param param 参数
* @return
*/
@GetMapping("/test")
public Result test(String java,String methodName,String param){
boolean write = FileUtil.write(java);
if(write){
try {
boolean flag=true;
//编译上传的java代码生成class文件
ProcessUtil.execCmd("javac d:/java/xiaow.java");
MyClassLoader myClassLoader=new MyClassLoader();
//使用我们自己定义的类加载器进行加载刚刚生成的class
Class<?> xiaow = myClassLoader.findclass("xiaow");
//如下都是反射内容 获取测试方法
Object o = xiaow.newInstance();
//这里是写死的,大家可以在数据库中获取
Method method = xiaow.getMethod(methodName,Integer.class);
// 对该方法进行测试
Set<Integer> set = map.keySet();
for (Integer integer : set) {
Integer integer1 = map.get(integer);
Integer invoke = (Integer) method.invoke(o,integer);
if(!invoke.equals(integer1)){
return Result.fail("WA");
}
}
return Result.succ("AC");
} catch (Exception e) {
e.printStackTrace();
}
}
return Result.fail("测试失败");
}
}
成果
然后再写一下前端,就结束了
艾玛,做了这么多年题,可算AC了