Java动态脚本Groovy

 更新时间:2021年12月14日 10:51:06   作者:南国以南i  
本文介绍了Java动态脚本Groovy,Groovy是用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。使用该种语言不必编写过多的代码,同时又具有闭包和动态语言中的其他特性,需要的朋友可以参考一下

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("==================");
    }
}

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;
    }


添加结果:

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

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

5.总语

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

到此这篇关于Java动态脚本Groovy的文章就介绍到这了,更多相关Java动态脚本Groovy内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一篇文章带你学习JAVA MyBatis底层原理

    一篇文章带你学习JAVA MyBatis底层原理

    近来想写一个mybatis的分页插件,但是在写插件之前肯定要了解一下mybatis具体的工作原理吧,本文就详细总结了MyBatis工作原理,,需要的朋友可以参考下
    2021-09-09
  • Spring Cloud Feign请求添加headers的实现方式

    Spring Cloud Feign请求添加headers的实现方式

    这篇文章主要介绍了Spring Cloud Feign请求添加headers的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • 如何实现Java中一个简单的LinkedList

    如何实现Java中一个简单的LinkedList

    LinkedList与ArrayList都是List接口的具体实现类。下面将介绍如何实现一个简单的LinkedList,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • 关于@Entity和@Table注解的用法详解

    关于@Entity和@Table注解的用法详解

    这篇文章主要介绍了关于@Entity和@Table注解的用法详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Idea 配置国内 Maven 源的图文教程

    Idea 配置国内 Maven 源的图文教程

    这篇文章主要介绍了Idea 配置国内 Maven 源的教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-11-11
  • JDBC建立数据库连接的代码

    JDBC建立数据库连接的代码

    这篇文章主要为大家详细介绍了JDBC建立数据库连接的代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • 初识MyBatis及基本配置和执行

    初识MyBatis及基本配置和执行

    这篇文章主要介绍了初识MyBatis的基本知识,文中给大家提到了mybatis基本配置和执行过程,需要的朋友可以参考下
    2017-11-11
  • Assert.assertEquals的使用方法及注意事项说明

    Assert.assertEquals的使用方法及注意事项说明

    这篇文章主要介绍了Assert.assertEquals的使用方法及注意事项说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • 解决FeignClient发送post请求异常的问题

    解决FeignClient发送post请求异常的问题

    这篇文章主要介绍了FeignClient发送post请求异常的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 从零构建可视化jar包部署平台JarManage教程

    从零构建可视化jar包部署平台JarManage教程

    这篇文章主要为大家介绍了从零构建可视化jar包部署平台JarManage教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05

最新评论