一招教你怎么用Java调用groovy脚本

知乎 · · 130 次点击 · · 开始浏览    

为什么要聊groovy呢?

其实Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了PythonRuby许多强大的特性,Groovy代码能够与Java代码很好地结合,也能用于扩展现有代码。

Groovy有哪些特点呢?

  1. 为Java开发者提供了 现代最流行的编程语言特性,而且学习成本很低(几乎为零)。
  2. Groovy拥有处理原生类型,面向对象以及一个Ant DSL,使得创建Shell Scripts变得非常简单。
  3. groovy中基本类型也是对象,可以直接调用对象的方法。
  4. 支持函数式编程,不需要main函数。
  5. 直接编译成Java字节码,这样可以在任何使用Java的地方 使用Groovy。

OK,接下来切入整体,介绍一下怎么通过Java调用Groovy脚本。

Java调用Groovy的几种方法

工具:IntelliJ IDEA

项目:maven项目

依赖:groovy-all包

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>3.0.7</version>
    <type>pom</type>
</dependency>

GroovyShell执行groovy脚本

  1. 通过evaluate方法执行groovy脚本

GroovyShell的evaluate方法非常类似于Js的eva方法,可执行一段字符串。

package com.robot.universalrobot.groovyTest;
import groovy.lang.GroovyShell;
import java.util.logging.Logger;
import org.codehaus.groovy.control.CompilationFailedException;
import java.io.IOException;
/**
 * @Date 2021/1/1 7:33 下午
 **/
public class Test_002 {
    public static void testGroovy2() throws CompilationFailedException, IOException {
        GroovyShell groovyShell = new GroovyShell();
        groovyShell.evaluate("println 'hello Groovy shell.'");
    }
    public static void main(String[] args) {
        try {
            testGroovy2();
        } catch (IOException error){
            error.getStackTrace();
        }
    }
}

运行结果



  1. 通过evaluate方法调用groovy脚本文件

需要将要建一个groovy文件,定义要执行的脚本,例如定义一个无参的方法sayHello并调用该方法。

def sayHello() {
    println 'Hello World.'
}
sayHello()

在Java中就可以直接调用这个groovy文件执行了,方法如下:

package com.robot.universalrobot.groovyTest;
import groovy.lang.GroovyShell;
import lombok.Data;
import org.codehaus.groovy.control.CompilationFailedException;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
/**
 * @Date 2021/1/1 7:26 下午
 **/
@Data
public class test_001 {
    public static void testGroovy1() throws CompilationFailedException, IOException {
        GroovyShell groovyShell = new GroovyShell();
        Object result = groovyShell.evaluate(new File("src/main/java/com/robot/universalrobot/groovyTest/demo_001.groovy"));
    }
    public static void main(String[] args) {
        try {
            testGroovy1();
        } catch (Exception error){
            error.getStackTrace();
        }
    }
}

执行结果



  1. 给groovy文件传参数并执行
package com.robot.universalrobot.groovyTest
def sayHello(name) {
    println 'Hello World.' + name
}
sayHello(name)

Java调用groovy方法

public class test_001 {
    public static void testGroovy1() throws CompilationFailedException, IOException {
        // 调用带参数的groovy shell时,使用bind绑定数据
        Binding binding = new Binding();
        binding.setProperty("name", "软件质量保障");
        GroovyShell groovyShell = new GroovyShell(binding);
        Object result = groovyShell.evaluate(new File("src/main/java/com/robot/universalrobot/groovyTest/demo_001.groovy"));
    }
    public static void main(String[] args) {
        try {
            testGroovy1();
        } catch (Exception error){
            error.getStackTrace();
        }
    }
}

执行结果



GroovyClassLoader动态加载Groovy Class

你也许熟悉Java的ClassLoader类加载器,当运行Java程序时,首先运行JVM(Java虚拟机),然后再把Java class加载到JVM运行,负责加载Java class的这部分就叫做Class Loader。而GroovyClassLoader,顾名思义,就是用来加载Groovy类的加载器。

  1. 新建groovy class
class demo_002 {
    String sayHello(String name, String sex, int age) {
        return "name: " + name + ", sex: " + sex + ", age: " + age;
    }
}
  1. 编写Java调用文件
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import org.codehaus.groovy.control.CompilerConfiguration;
import java.io.File;
/**
 * @Date 2021/1/1 7:58 下午
 **/
public class Test_003 {
    private static GroovyClassLoader groovyClassLoader = null;
    public static void initGroovyClassLoader() {
        CompilerConfiguration config = new CompilerConfiguration();
        config.setSourceEncoding("UTF-8");
        // 设置该GroovyClassLoader的父ClassLoader为当前线程的加载器(默认)
        groovyClassLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config);
    }
    /**
     * 通过GroovyClassLoader加载GroovyShell_2,并反射调用其sayHello(String name, String sex, int age)方法
     *
     */
    public static String invokeSayHello(String name, String sex, int age) {
        String result = "";
        File groovyFile = new File("src/main/java/com/robot/universalrobot/groovyTest/demo_002.groovy");
        if (!groovyFile.exists()) {
            return result;
        }
        try {
            // 获得GroovyShell_2加载后的class
            Class<?> groovyClass = groovyClassLoader.parseClass(groovyFile);
            // 获得GroovyShell_2的实例
            GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
            // 反射调用sayHello方法得到返回值
            Object methodResult = groovyObject.invokeMethod("sayHello", new Object[] {name, sex, age});
            if (methodResult != null) {
                result = methodResult.toString();
            }
        } catch (Exception e) {
            e.getStackTrace();
        }
        return result;
    }
    public static void main(String[] args) throws Exception {
        initGroovyClassLoader();
        System.out.println(invokeSayHello("张三", "男", 25));
    }
}

执行结果

其方式和Java中类的加载反射类似,这里不再熬述。需要注意的是GroovyClassLoader与Java中的加载器一样,同一个类名的类只能加载一次,如果想再次加载,必须调用GroovyClassLoader的clearCache()方法移除所有已经加载的Groovy Class。

GroovyScriptEngine脚本引擎加载Groovy脚本

GroovyScriptEngine从指定的位置(文件系统,URL,数据库等等)加载Groovy脚本,并且随着脚本变化可重新加载它们。GroovyScriptEngine也可以传进变量值返回脚本的计算结果。

以上面栗子中的groovy文件为例。

编写使用GroovyScriptEngine从com.juxinli.groovy.shell包中加载、运行这些script

package com.robot.universalrobot.groovyTest;
import groovy.util.GroovyScriptEngine;
import groovy.lang.Binding;
/**
 * @Date 2021/1/1 8:07 下午
 **/
public class test_004 {
    public static void main(String[] args) throws Exception {
        // GroovyScriptEngine的根路径,如果参数是字符串数组,说明有多个根路径
        GroovyScriptEngine engine = new GroovyScriptEngine("src/main/java/com/robot/universalrobot/groovyTest");
        Binding binding = new Binding();
        binding.setVariable("name", "软件质量保障");
        Object result1 = engine.run("demo_001.groovy", binding);
        Object result2 = engine.run("demo_003.groovy", binding);
    }
}

执行结果

好啦,以上就是总结的几种执行groovy脚本的方法,欢迎转载分享。

参考文档

tool.oschina.net/apidoc

本文来自:知乎

感谢作者:知乎

查看原文:一招教你怎么用Java调用groovy脚本

130 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传