最近设计一个数据统计系统,系统中上百种数据统计维度,而且这些数据统计的指标可能随时会调整.如果基于java编码的方式逐个实现数据统计的API设计,工作量大而且维护起来成本较高;最终确定为将"数据统计"的计算部分单独分离成脚本文件(javascript,或者Groovy),非常便捷了实现了"数据统计Task" 与 "数据统计规则(计算)"解耦,且可以动态的加载和运行的能力.顺便对JAVA嵌入运行Groovy脚本做个备忘.
Java中运行Groovy,有三种比较常用的类支持:GroovyShell,GroovyClassLoader以及Java-Script引擎(JSR-223).
1) GroovyShell: 通常用来运行"script片段"或者一些零散的表达式(Expression)
2) GroovyClassLoader: 如果脚本是一个完整的文件,特别是有API类型的时候,比如有类似于JAVA的接口,面向对象设计时,通常使用GroovyClassLoader.
3) ScriptEngine: JSR-223应该是推荐的一种使用策略.规范化,而且简便.
一.GroovyShell代码样例
1) 简单的表达式执行,方法调用
-
-
-
-
-
publicstaticvoidevalScriptText()throwsException{
-
-
Bindingbinding=newBinding();
-
GroovyShellshell=newGroovyShell(binding);
-
-
binding.setVariable("name","zhangsan");
-
shell.evaluate("println'HelloWorld!Iam'+name;");
-
-
shell.evaluate("date=newDate();");
-
Datedate=(Date)binding.getVariable("date");
-
System.out.println("Date:"+date.getTime());
-
-
-
Longtime=(Long)shell.evaluate("deftime=date.getTime();returntime;");
-
System.out.println("Time:"+time);
-
binding.setVariable("list",newString[]{"A","B","C"});
-
-
StringjoinString=(String)shell.evaluate("defcall(){returnlist.join('-')};call();");
-
System.out.println("Arrayjoin:"+joinString);
-
shell=null;
-
binding=null;
-
}
2) 伪main方法执行.
-
-
-
-
publicstaticvoidevalScriptAsMainMethod(){
-
String[]args=newString[]{"Zhangsan","10"};
-
Bindingbinding=newBinding(args);
-
GroovyShellshell=newGroovyShell(binding);
-
shell.evaluate("staticvoidmain(String[]args){if(args.length!=2)return;println('Hello,Iam'+args[0]+',age'+args[1])}");
-
shell=null;
-
binding=null;
-
}
3) 通过Shell运行具有类结构的Groovy脚本
-
-
-
-
-
publicstaticvoidevalScriptTextFull()throwsException{
-
StringBufferbuffer=newStringBuffer();
-
-
buffer.append("classUser{")
-
.append("Stringname;Integerage;")
-
-
.append("StringsayHello(){return'Hello,Iam'+name+',age'+age;}}\n");
-
-
buffer.append("defuser=newUser(name:'zhangsan',age:1);")
-
.append("user.sayHello();");
-
-
Bindingbinding=newBinding();
-
GroovyShellshell=newGroovyShell(binding);
-
Stringmessage=(String)shell.evaluate(buffer.toString());
-
System.out.println(message);
-
-
StringmainMethod="staticvoidmain(String[]args){defuser=newUser(name:'lisi',age:12);print(user.sayHello());}";
-
shell.evaluate(mainMethod);
-
shell=null;
-
}
4) 方法执行和分部调用
-
-
-
-
-
publicstaticvoidevalScript()throwsException{
-
Bindingbinding=newBinding();
-
GroovyShellshell=newGroovyShell(binding);
-
-
-
Scriptscript=shell.parse("defjoin(String[]list){returnlist.join('--');}");
-
StringjoinString=(String)script.invokeMethod("join",newString[]{"A1","B2","C3"});
-
System.out.println(joinString);
-
-
-
-
script=shell.parse("staticvoidmain(String[]args){i=i*2;}");
-
script.setProperty("i",newInteger(10));
-
script.run();
-
System.out.println(script.getProperty("i"));
-
-
System.out.println(script.getBinding().getVariable("i"));
-
script=null;
-
shell=null;
-
}
二. GroovyClassLoader代码示例
1) 解析groovy文件
-
-
-
-
publicstaticvoidparse()throwsException{
-
GroovyClassLoaderclassLoader=newGroovyClassLoader(Thread.currentThread().getContextClassLoader());
-
FilesourceFile=newFile("D:\\TestGroovy.groovy");
-
ClasstestGroovyClass=classLoader.parseClass(newGroovyCodeSource(sourceFile));
-
GroovyObjectinstance=(GroovyObject)testGroovyClass.newInstance();
-
Longtime=(Long)instance.invokeMethod("getTime",newDate());
-
System.out.println(time);
-
Datedate=(Date)instance.invokeMethod("getDate",time);
-
System.out.println(date.getTime());
-
-
instance=null;
-
testGroovyClass=null;
-
}
2) 如何加载已经编译的groovy文件(.class)
-
publicstaticvoidload()throwsException{
-
GroovyClassLoaderclassLoader=newGroovyClassLoader(Thread.currentThread().getContextClassLoader());
-
BufferedInputStreambis=newBufferedInputStream(newFileInputStream("D:\\TestGroovy.class"));
-
ByteArrayOutputStreambos=newByteArrayOutputStream();
-
for(;;){
-
inti=bis.read();
-
if(i==-1){
-
break;
-
}
-
bos.write(i);
-
}
-
ClasstestGroovyClass=classLoader.defineClass(null,bos.toByteArray());
-
-
-
-
GroovyObjectinstance=(GroovyObject)testGroovyClass.newInstance();
-
Longtime=(Long)instance.invokeMethod("getTime",newDate());
-
System.out.println(time);
-
Datedate=(Date)instance.invokeMethod("getDate",time);
-
System.out.println(date.getTime());
-
-
-
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) 代码样例
-
publicstaticvoidevalScript()throwsException{
-
ScriptEngineManagerfactory=newScriptEngineManager();
-
-
ScriptEngineengine=factory.getEngineByName("groovy");
-
System.out.println(engine.toString());
-
assertengine!=null;
-
-
Bindingsbinding=engine.createBindings();
-
binding.put("date",newDate());
-
-
engine.eval("defgetTime(){returndate.getTime();}",binding);
-
engine.eval("defsayHello(name,age){return'Hello,Iam'+name+',age'+age;}");
-
Longtime=(Long)((Invocable)engine).invokeFunction("getTime",null);
-
System.out.println(time);
-
Stringmessage=(String)((Invocable)engine).invokeFunction("sayHello","zhangsan",newInteger(12));
-
System.out.println(message);
-
}
需要提醒的是,在groovy中,${expression} 将会被认为一个变量,如果需要输出"$"符号,需要转义为"\$".
关于ScriptEngine更多介绍,请参考.
分享到:
相关推荐
Java调用Groovy,实时动态加载数据库groovy脚本,java读取mongoDB的groovy脚本,加载实时运行,热部署
干货:Jenkins Pipeline调用shell、python、java、groovy脚本的正确使用姿势.doc
groovy脚本实现对数据库的增删改查,groovy脚本不需要编译,十分实用
}二. GroovyClassLoader代码示例 1) 解析groovy文件 /** * from source file of *.groovy */
Java中使用Groovy的三种方式,详细见我的博客。
java 动态脚本语言 精通 Groovy
脚本通过上下文applicationcontext获取被测试应用bean,从而可以进行接口内容获取等操作。目前该方式主要运用到性能平台脚本搭建、代码深度测试、接口测试、白盒测试等多方面。...支持Java、groovy脚本。
java嵌入groovy所需jar 2.3.7最新版
java运行groovy 环境,搭建方便自己练习groovy使用 与后续定时调度动态代码做准备
Groovy 调用 Java 类groovy 调用 Java class 十分方便,只需要在类前导入该 Java 类,在 Groovy 代码中就可以无缝使用该
Android Studio中的Gradle开发脚本语言Groovy,Groovy入门,以及精通
对javax.script包进行讲解,实现支持java动态嵌入执行groovy代码片段
项目从es2升级到es6,groovy脚本也要相应的转换为painless脚本,转换过程中遇到了很多坑,特此总结成文档,供大家一起交流学习。
执行测试开发过程中的groovy脚本,无须安装,解压即可使用,直接运行bin目录下的groovyConsole.bat即可。
groovy脚本语言bin groovy-binary-1.6.5.zip
Making Java Groovy is a practical handbook for developers who want to blend Groovy into their day to day work with Java It starts by introducing the key differences between Java and Groovy and how you...
概述主要介绍Java、spring与groovy结合使用,高清英文版本
Making Java Groovy
动态加载指定目录下的groovy脚本,并将其注册为groovy bean,放置于ApplicationContext容器中,并使用命名空间进行分类区分(一个namespace对应于一个ApplicationContext)。同时能够动态感知到groovy脚本的新增、修改...
问题原因分析:使用ScriptEngine.eval每次都会对脚本进行编译,生成一个新的类,被GroovyClassLoader加载,大量执行计算后,将导致被加载的类数量不断增加,最终OOM。 解决办法:对计算的表达式expression进行预...