本文章流程
页面保存form表单—>存储到mysql—>项目中读取—>动态加载到内存中
之所以有这样的设计. 是需要动态的加载过滤文件的算法. 因为需求是一直变化的. 今天用A方法, 可能明天就需要改为B方法. 不能频繁改动源码的情况下 可以使用动态加载类的 方式实现
比如现在有个外部的.java文件
package com.example.boottest.rule;
import com.example.boottest.easyrule.BaseRule;
import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;
@Rule
public class DemoRule1 extends BaseRule {
@Condition
public boolean when(@Fact("param1") String param1) {
System.out.println("我是参数1,value=" + param1);
return true;
}
@Action
public void then(@Fact("param2") String param2) {
System.out.println("我是参数2,value=" + param2);
}
}
我可以通过页面把这个类 通过以字符串或者byte[]的形式 传递到后端.
后端用的数组接收
/**
* java 源文件
*/
private byte[] byteContent;
数据库接收为:longblob 用于存储byte[]
具体动态加载代码:
注意跟上面的.java对应起来;
思路:
- 从数据库获取之前的源码byte[];
- 写入一个临时的.java文件
- 通过javatool的工具获取编译对象
- 执行编译.
- 通过class.forname获取class对象
- 通过newInstance获取具体的obj
其中步骤3时踩坑了. 没有加载到javatool工具.
参考:https://blog.youkuaiyun.com/qq_39514033/article/details/103999277
下面有注释.
/**
* 从JavaRuleDO获取规则Class对象
*
* @param javaRule
* @throws Exception
*/
public static Class<?> getRuleClassWithFile(JavaRule javaRule) throws Exception {
try {
//javaRule.getFileName(): DemoRule1
//生成临时的 .java文件: /data/DemoRule1.java
String filePath = "/data/" + javaRule.getFileName() + ".java";
//这个FileUtil是 hutool包里面的
BufferedOutputStream outputStream = FileUtil.getOutputStream(filePath);
outputStream.write(javaRule.getByteContent());
outputStream.flush();
outputStream.close(); //应该在finally代码块中 懒得改
// 然后生成class文件
//locationPath :/C:/Users/Lenovo/IdeaProjects/mytest/boot-test/target/classes/
//存放.class文件的地方
String locationPath = Thread.currentThread().getContextClassLoader ().getResource("").getPath();
log.info(locationPath);
//主要代码在这里
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
int status = javac.run(null, null, null, "-d", locationPath,
filePath);
if (status != 0) {
System.out.println("没有编译成功!");
}
//动态执行
//返回与带有给定字符串名的类 或接口相关联的 Class 对象。
//javaRule.getFullClassName():com.example.boottest.easyrule.DemoRule1
//注意类的全路径名 我在这里踩坑了
Class clz = Class.forName(javaRule.getFullClassName());
Object o = clz.newInstance();
return clz;
} catch (Exception e) {
log.error("加载类{}异常!", javaRule.getFileName());
throw e;
}
}
这里只有一些思想. 没有具体的代码实现. 可以自己实现下 应该也不难的;
我已经成功获取到了对象. 但是公司网络原因 无法上图