Java动态脚本Groovy

作者:南国以南i 时间:2023-12-05 03:25:50 

目录
  • 1.Groovy特性

  • 2.核心涉及

  • 3.Java与Groovy转换

    • 第一步:引入Groovy依赖

    • 第二步:创建interface接口声明方法

    • 第三步:在resources目录下创建.groovy文件

    • 第四步:创建Groovy脚本装载类,动态解析脚本为Class

    • 第五步:读取脚本内容,执行脚本

  • 4.Groovy特性验证

    • 第一步:将之前Groovy脚本数据修改。存于数据库表中,动态加载脚本

    • 第二步:数据库表中:添加、查询Groovy脚本,动态加载执行

    • 第三步:多次修改表数据值,查看执行结果

  • 5.总语

    1.Groovy特性

    可将java代码在Groovy脚本动态编码、代码被修改达到不重启服务的目的(类似于热部署)

    2.核心涉及

    • ClassLoader:就是类的装载器,它使JVM可以动态的载入Java类,JVM并不需要知道从什么地方(本地文件、网络等)载入Java类,这些都由ClassLoader完成。

    • GroovyClassLoader:动态地加载一个脚本并执行它的行为。GroovyClassLoader是一个定制的类装载器,负责解释加载Java类中用到的Groovy类。

    3.Java与Groovy转换

    第一步:引入Groovy依赖


      <!--Groovy脚本依赖-->
           <dependency>
               <groupId>org.codehaus.groovy</groupId>
               <artifactId>groovy</artifactId>
               <version>2.5.14</version>
           </dependency>

    第二步:创建interface接口声明方法


    public interface CallAnalysis {
        default void load() {
       }
    }

    第三步:在resources目录下创建.groovy文件


    package groovy

    import com.example.groovy.testgroovy.task.CallAnalysis
    import groovy.util.logging.Slf4j

    @Slf4j
    class CallAnalysisImpl implements CallAnalysis{

    @Override
       void load() {
           log.info("我被Groovy脚本加载...")
       }
    }

    第四步:创建Groovy脚本装载类,动态解析脚本为Class


    package com.example.groovy.testgroovy.task;

    import groovy.lang.GroovyClassLoader;

    public class GroovyUtils {

    private final static ClassLoader classLoader = GroovyUtils.class.getClassLoader();//获取当前类装载器
       //ClassLoader:就是类的装载器,它使JVM可以动态的载入Java类,JVM并不需要知道从什么地方(本地文件、网络等)载入Java类,这些都由ClassLoader完成。

    public final static GroovyClassLoader groovyClassLoader = new GroovyClassLoader(classLoader);
       //GroovyClassLoader:负责在运行时编译groovy源代码为Class的工作,从而使Groovy实现了将groovy源代码动态加载为Class的功能。

    /**
        * .
        * 获取实例化对象
        * @param script groovy脚本内容
        * @param <T>
        * @return
        * @throws IllegalAccessException
        * @throws InstantiationException
        */
       public static <T> T instanceTaskGroovyScript(String script) throws IllegalAccessException, InstantiationException {
           Class taskClz = groovyClassLoader.parseClass(script);
           T instance = (T) taskClz.newInstance();
           return instance;
       }
    }

    第五步:读取脚本内容,执行脚本


    package com.example.groovy.testgroovy.task;

    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.io.FileUtils;
    import org.springframework.stereotype.Component;

    import java.io.File;
    import java.io.IOException;

    @Slf4j
    @Component
    public class CallAnalysisGroovyTask {

    /**
        * .
        * 读取脚本内容
        *
        * @return
        */
       public static String getGroovy() {
           String context = "";
           try {
               String path = "E:\\IDEAFile\\testgroovy\\src\\main\\resources\\groovy\\CallAnalysisImpl.groovy";
               context = FileUtils.readFileToString(new File(path));//将脚本内容转为字符串
           } catch (IOException e) {
               log.error("file is not found[{}]", e);
           }
           return context;
       }

    /**
        * .
        * 执行groovy脚本
        *
        * @param script
        */
       public static void execGroovy(String script) {
           try {
               CallAnalysis objClass = GroovyUtils.instanceTaskGroovyScript(script);//获取实例对象
               objClass.load();//调用脚本方法
           } catch (Exception t) {
               log.error("execGroovy file {} error", script);
           }
       }

    /**
        * .
        * main方法
        * @param args
        */
       public static void main(String[] args) {
           System.out.println("==================");
           CallAnalysisGroovyTask task = new CallAnalysisGroovyTask();
           String script = task.getGroovy();//获取脚本
           execGroovy(script);//实例化脚本,执行方法
           System.out.println("==================");
       }
    }

    Java动态脚本Groovy

    4.Groovy特性验证

    利用Groovy脚本特性,不重启服务,实时修改数据

    第一步:将之前Groovy脚本数据修改。存于数据库表中,动态加载脚本


    @Slf4j
    class CallAnalysisImpl implements CallAnalysis {

    private int anInt = 10;
       private int bnInt = 10;

    @Override
       void load() {
           log.info("当前类:[{}]", this.getClass().getName())
           log.info("我被Groovy脚本加载...")
           log.info("计算结果:[{}]", (anInt + bnInt))
       }
    }

    第二步:数据库表中:添加、查询Groovy脚本,动态加载执行


    /**
        * .
        * 读取脚本,进行入库操作
        *
        * @return
        */
       @GetMapping("/saveScript")
       public String saveScript() {
           String scriptStr = callAnalysisGroovyTask.getGroovy();
           Script script = new Script();//实体类对象
           script.setScript(scriptStr);//脚本内容
           script.setRuleId("1");//规则id
           script.setScriptName("演示一");//脚本名称
           service.save(script);
           return "添加成功";
       }

    /**
        * .
        * 从数据库表中,动态获取脚本
        *
        * @param ruleId 规则id
        * @return 脚本内容
        */
       @GetMapping("/groovy")
       public String groovy(final String ruleId) {
           Script scr = scriptService.findScriptByRuleId(ruleId);//根据规则id查询
           String scriptStr = scr.getScript();
           callAnalysisGroovyTask.execGroovy(scriptStr);
           return scriptStr;
       }

    添加结果:

    Java动态脚本Groovy

     查询结果、控制台执行结果:

    Java动态脚本Groovy

    第三步:多次修改表数据值,查看执行结果

    Java动态脚本Groovy

    5.总语

    目的达成,可见在不重启服务时,多次修改数据,脚本内容都会被动态加载。此处只是简单举例验证,可自行扩展

    来源:https://www.cnblogs.com/bgyb/p/15683719.html

    标签:Java,动态脚本,Groovy
    0
    投稿

    猜你喜欢

  • SpringBoot日志框架之Log4j2快速入门与参数详解

    2023-11-15 21:17:59
  • Service Activity的三种交互方式(详解)

    2022-03-16 20:55:08
  • SpringCloud微服务架构升级汇总

    2022-05-04 06:09:19
  • Java 容器类源码详解 Set

    2022-03-21 18:08:40
  • C#图像颜色聚类高效方法实例

    2021-09-29 09:14:41
  • Android使用TransitionDrawable渐变切换多张图片

    2023-01-08 16:27:22
  • App内切换语言详解

    2023-04-12 11:21:44
  • RollViewPager图片轮播效果开源框架使用方法详解

    2021-12-06 07:22:59
  • c#中switch case的用法实例解析

    2023-09-20 23:02:51
  • docker 的java编译环境构建详细介绍

    2023-02-10 04:08:30
  • Java中lombok的@Builder注解的解析与简单使用详解

    2022-12-29 06:44:55
  • SpringBoot整合WebSocket的客户端和服务端的实现代码

    2023-03-30 04:19:07
  • 使用cmd根据WSDL网址生成java客户端代码的实现

    2022-09-12 11:00:20
  • C#程序调用cmd.exe执行命令

    2022-11-14 04:04:50
  • mybatis查询返回Map<String,Object>类型的讲解

    2022-12-25 02:07:38
  • java线程之用Thread类创建线程的方法

    2023-02-09 18:35:07
  • C++中String类型的逆序方式

    2023-11-19 05:46:52
  • 关于Spring事务隔离、传播属性与@Transactional注解

    2021-11-15 04:37:11
  • C# TSC打印二维码和条形码的实现方法

    2021-10-06 14:39:53
  • Android手机获取IP地址的两种方法

    2021-05-28 14:18:51
  • asp之家 软件编程 m.aspxhome.com