为什么要聊groovy呢?
其实Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python和Ruby许多强大的特性,Groovy代码能够与Java代码很好地结合,也能用于扩展现有代码。
Groovy有哪些特点呢?
- 为Java开发者提供了 现代最流行的编程语言特性,而且学习成本很低(几乎为零)。
- Groovy拥有处理原生类型,面向对象以及一个Ant DSL,使得创建Shell Scripts变得非常简单。
- groovy中基本类型也是对象,可以直接调用对象的方法。
- 支持函数式编程,不需要main函数。
- 直接编译成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脚本
- 通过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();
}
}
}
运行结果
- 通过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();
}
}
}
执行结果
- 给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类的加载器。
- 新建groovy class
class demo_002 {
String sayHello(String name, String sex, int age) {
return "name: " + name + ", sex: " + sex + ", age: " + age;
}
}
- 编写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脚本的方法,欢迎转载分享。
参考文档