java动态加载类/.java文件/通过mysql读取源码

本文章流程

页面保存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对应起来;

思路:

  1. 从数据库获取之前的源码byte[];
  2. 写入一个临时的.java文件
  3. 通过javatool的工具获取编译对象
  4. 执行编译.
  5. 通过class.forname获取class对象
  6. 通过newInstance获取具体的obj

其中步骤3时踩坑了. 没有加载到javatool工具.
参考:https://blog.csdn.net/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;
        }
    }

这里只有一些思想. 没有具体的代码实现. 可以自己实现下 应该也不难的;

我已经成功获取到了对象. 但是公司网络原因 无法上图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值