JAVA嵌入运行Groovy脚本

一.GroovyShell代码样例

1) 简单的表达式执行,方法调用

/**
 * 简答脚本执行
 * @throws Exception
 */
public static void evalScriptText() throws Exception{
	//groovy.lang.Binding
	Binding binding = new Binding();
	GroovyShell shell = new GroovyShell(binding);

	binding.setVariable("name", "zhangsan");
	shell.evaluate("println ‘Hello World! I am ‘ + name;");
	//在script中,声明变量,不能使用def,否则scrope不一致.
	shell.evaluate("date = new Date();");
	Date date = (Date)binding.getVariable("date");
	System.out.println("Date:" + date.getTime());
	//以返回值的方式,获取script内部变量值,或者执行结果
	//一个shell实例中,所有变量值,将会在此"session"中传递下去."date"可以在此后的script中获取
	Long time = (Long)shell.evaluate("def time = date.getTime(); return time;");
	System.out.println("Time:" + time);
	binding.setVariable("list", new String[]{"A","B","C"});
	//invoke method
	String joinString = (String)shell.evaluate("def call(){return list.join(‘ - ‘)};call();");
	System.out.println("Array join:" + joinString);
	shell = null;
	binding = null;
}

2)  伪main方法执行.

/**
 * 当groovy脚本,为完整类结构时,可以通过执行main方法并传递参数的方式,启动脚本.
 */
public static void evalScriptAsMainMethod(){
	String[] args = new String[]{"Zhangsan","10"};//main(String[] args)
	Binding binding = new Binding(args);
	GroovyShell shell = new GroovyShell(binding);
	shell.evaluate("static void main(String[] args){ if(args.length != 2) return;println(‘Hello,I am ‘ + args[0] + ‘,age ‘ + args[1])}");
	shell = null;
	binding = null;
}

3)  通过Shell运行具有类结构的Groovy脚本

/**
 * 运行完整脚本
 * @throws Exception
 */
public static void evalScriptTextFull() throws Exception{
	StringBuffer buffer = new StringBuffer();
	//define API
	buffer.append("class User{")
			.append("String name;Integer age;")
			//.append("User(String name,Integer age){this.name = name;this.age = age};")
			.append("String sayHello(){return ‘Hello,I am ‘ + name + ‘,age ‘ + age;}}\n");
	//Usage
	buffer.append("def user = new User(name:‘zhangsan‘,age:1);")
			.append("user.sayHello();");
	//groovy.lang.Binding
	Binding binding = new Binding();
	GroovyShell shell = new GroovyShell(binding);
	String message = (String)shell.evaluate(buffer.toString());
	System.out.println(message);
	//重写main方法,默认执行
	String mainMethod = "static void main(String[] args){def user = new User(name:‘lisi‘,age:12);print(user.sayHello());}";
	shell.evaluate(mainMethod);
	shell = null;
}

4)  方法执行和分部调用

/**
 * 以面向"过程"的方式运行脚本
 * @throws Exception
 */
public static void evalScript() throws Exception{
 Binding binding = new Binding();
 GroovyShell shell = new GroovyShell(binding);
 //直接方法调用
 //shell.parse(new File(//))
 Script script = shell.parse("def join(String[] list) {return list.join(‘--‘);}");
 String joinString = (String)script.invokeMethod("join", new String[]{"A1","B2","C3"});
 System.out.println(joinString);
 ////脚本可以为任何格式,可以为main方法,也可以为普通方法
 //1) def call(){...};call();
 //2) call(){...};
 script = shell.parse("static void main(String[] args){i = i * 2;}");
 script.setProperty("i", new Integer(10));
 script.run();//运行,
 System.out.println(script.getProperty("i"));
 //the same as
 System.out.println(script.getBinding().getVariable("i"));
 script = null;
 shell = null;
}

二. GroovyClassLoader代码示例

1) 解析groovy文件

/**
 * from source file of *.groovy
 */
public static void parse() throws Exception{
	GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader());
	File sourceFile = new File("D:\\TestGroovy.groovy");
	Class testGroovyClass = classLoader.parseClass(new GroovyCodeSource(sourceFile));
	GroovyObject instance = (GroovyObject)testGroovyClass.newInstance();//proxy
	Long time = (Long)instance.invokeMethod("getTime", new Date());
	System.out.println(time);
	Date date = (Date)instance.invokeMethod("getDate", time);
	System.out.println(date.getTime());
	//here
	instance = null;
	testGroovyClass = null;
}

2) 如何加载已经编译的groovy文件(.class)

public static void load() throws Exception {
	GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader());
	BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\TestGroovy.class"));
	ByteArrayOutputStream bos = new ByteArrayOutputStream();
	for(;;){
		int i = bis.read();
		if( i == -1){
			break;
		}
		bos.write(i);
	}
	Class testGroovyClass = classLoader.defineClass(null, bos.toByteArray());
	//instance of proxy-class
	//if interface API is in the classpath,you can do such as:
	//MyObject instance = (MyObject)testGroovyClass.newInstance()
	GroovyObject instance = (GroovyObject)testGroovyClass.newInstance();
	Long time = (Long)instance.invokeMethod("getTime", new Date());
	System.out.println(time);
	Date date = (Date)instance.invokeMethod("getDate", time);
	System.out.println(date.getTime());

	//here
bis.close();
	bos.close();
	instance = null;
	testGroovyClass = null;
}

三. ScriptEngine

1) pom.xml依赖

<dependency>
	<groupId>org.codehaus.groovy</groupId>
	<artifactId>groovy</artifactId>
	<version>2.1.6</version>
</dependency>
<dependency>
	<groupId>org.codehaus.groovy</groupId>
	<artifactId>groovy-jsr223</artifactId>
	<version>2.1.6</version>
</dependency>

2) 代码样例

public static void evalScript() throws Exception{
	ScriptEngineManager factory = new ScriptEngineManager();
	//每次生成一个engine实例
	ScriptEngine engine = factory.getEngineByName("groovy");
	System.out.println(engine.toString());
	assert engine != null;
	//javax.script.Bindings
	Bindings binding = engine.createBindings();
	binding.put("date", new Date());
	//如果script文本来自文件,请首先获取文件内容
	engine.eval("def getTime(){return date.getTime();}",binding);
	engine.eval("def sayHello(name,age){return ‘Hello,I am ‘ + name + ‘,age‘ + age;}");
	Long time = (Long)((Invocable)engine).invokeFunction("getTime", null);
	System.out.println(time);
	String message = (String)((Invocable)engine).invokeFunction("sayHello", "zhangsan",new Integer(12));
	System.out.println(message);
}

需要提醒的是,在groovy中,${expression} 将会被认为一个变量,如果需要输出"$"符号,需要转义为"\$".

关于ScriptEngine更多介绍,请参考. http://shift-alt-ctrl.iteye.com/blog/1896690

时间: 2024-07-28 17:06:17

JAVA嵌入运行Groovy脚本的相关文章

JAVA与groovy脚本的结合使用

java执行groovy shell脚本 <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.0-beta-1</version> </dependency> 添加groovy jar包支持 ====================================

即时编译和打包您的 Groovy 脚本(转)

在本文中将会涉及到: 使用 CliBuilder 来实现对命令行选项的支持,脚本执行时所需要的参数将通过命令行选项的方式传递. 使用 GroovyClassLoader 加载 Groovy class. 使用 AntBuilder 来构建 Jar 包. 开始之前 关于本文 也许您写了一些有趣或实用的 Groovy 脚本并希望与您的朋友分享,可是您并不想强迫他们安装 Groovy,所以您也许想要做一个小工具让您的朋友们能够用它编译您的 Groovy 脚本并且生成一个可执行的 Jar 包.本文将介绍

【java web】java执行预编译Groovy脚本

在JVM中运行Groovy类有两种方式: 使用Groovy编译所有的*.groovy为java的*.class文件,把这些*.class文件放在java类路径中,通过java类加载器来加载这些类. 通过groovy类加载器在运行时直接加载*.groovy文件并生成对象.在这种方式下,没有生成任何*.class,但是生成了一个java.lang.Class对象的实例. 下面介绍前一种使用Groovy的方法:编译成java字节码并且作为正常java应用程序运行在java虚拟机上,即预编译模式. 1.

Java执行groovy脚本

1 Binding binding = new Binding(); 2 binding.setVariable("foo", new Integer(2)); 3 GroovyShell shell = new GroovyShell(binding); 4 5 String script = "import com.myb.to.infrastructure.Md5Util; " 6 + "def a = 12; println 'C# md5:' +

Linux(centos 6.5) 调用java脚本以及定时运行的脚本实例及配置文件具体解释

Linux(centos 6.5) 调用java脚本以及定时运行的脚本实例 一.调用java程序脚本(默认已经搭建好了Java环境) 1.jdk 安装路径 /usr/jdk/jdk1.7/-- 2.java 程序路径 /usr/jdk 3.类名:Test.java(有主函数的类名) 4.调用java类的脚本,注意脚本的后缀是.sh 5.脚本内容: (1)#! /bin/bash // #! 特殊符号.说明这个脚本是由/bin 文件夹下的bash这个shell来解释并将解释后的内容给kernel来

如何在Java平台上使用脚本语言做Java开发

如何在Java平台上使用脚本语言做Java开发     最近开始流行区分Java平台和Java语言,但很多Java开发者还是不能确定如何在 Java应用程序开发中结合脚本.本篇文章,Gregor Roth给出了在Java平台上使用脚本的方法.通过这篇文章,你可以了解怎样在你的Java应用程序中使用脚本,是否你要通过使用Groovy和 Jython把不同的Java应用程序模块粘合在一起,或者写一个你自己的基于JRuby的应用程序,适用于Java平台. 作为一个Java开发者,你可能已经注意到了,J

ElasticSearch Groovy脚本远程代码执行漏洞

什么是ElasticSearch? 它是一种分布式的.实时性的.由JAVA开发的搜索和分析引擎. 2014年,曾经被曝出过一个远程代码执行漏洞(CVE-2014-3120),漏洞出现在脚本查询模块,由于搜索引擎支持使用脚本代码(MVEL),作为表达式进行数据操作,攻击者可以通过MVEL构造执行任意java代码,后来脚本语言引擎换成了Groovy,并且加入了沙盒进行控制,危险的代码会被拦截,结果这次由于沙盒限制的不严格,导致远程代码执行任意命令..."任意"你懂的,比如:利用nc反弹sh

groovy脚本导致的FullGC问题

这个是由一个线上问题导致的: 背景: 应用中内嵌了groovy引擎,会动态执行传入的表达式并返回执行结果 线上问题: 发现机器的fullGC从某个时候开始暴涨,并且一直持续: 登到机器上,用jstat -gcutil 命令观察,发现perm区一直是100%,fullGC无法回收: 将这台机器的内存dump出来进行分析: 在类视图中,发现大量的groovy.lang.GroovyClassLoader$InnerLoader; 在类加载器视图里面也看到大量的groovy的InnerLoader:

Java到处运行的基础之 Class 文件

Java 实现一次编译到处运行的基础,来源于 Java 虚拟机屏蔽了操作系统的底层细节.使用 class 文件存储编译后的源程序,使得 Java 程序的编译与操作系统解耦.正是因为 Java class 文件的设计与 Java 语言解耦,分别发布了 Java语言规范和 Java 虚拟机规范,使得其他语言如Scala.Groovy.JRuby.JPython 等基于Java 虚拟机的语言按照 class 文件格式要求生成的class 文件也能在虚拟机上运行. class 文件格式 class 文件