`
samwong
  • 浏览: 287608 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA嵌入运行Groovy脚本

 
阅读更多

最近设计一个数据统计系统,系统中上百种数据统计维度,而且这些数据统计的指标可能随时会调整.如果基于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) 简单的表达式执行,方法调用

Java代码收藏代码
  1. /**
  2. *简答脚本执行
  3. *@throwsException
  4. */
  5. publicstaticvoidevalScriptText()throwsException{
  6. //groovy.lang.Binding
  7. Bindingbinding=newBinding();
  8. GroovyShellshell=newGroovyShell(binding);
  9. binding.setVariable("name","zhangsan");
  10. shell.evaluate("println'HelloWorld!Iam'+name;");
  11. //在script中,声明变量,不能使用def,否则scrope不一致.
  12. shell.evaluate("date=newDate();");
  13. Datedate=(Date)binding.getVariable("date");
  14. System.out.println("Date:"+date.getTime());
  15. //以返回值的方式,获取script内部变量值,或者执行结果
  16. //一个shell实例中,所有变量值,将会在此"session"中传递下去."date"可以在此后的script中获取
  17. Longtime=(Long)shell.evaluate("deftime=date.getTime();returntime;");
  18. System.out.println("Time:"+time);
  19. binding.setVariable("list",newString[]{"A","B","C"});
  20. //invokemethod
  21. StringjoinString=(String)shell.evaluate("defcall(){returnlist.join('-')};call();");
  22. System.out.println("Arrayjoin:"+joinString);
  23. shell=null;
  24. binding=null;
  25. }

2) 伪main方法执行.

Java代码收藏代码
  1. /**
  2. *当groovy脚本,为完整类结构时,可以通过执行main方法并传递参数的方式,启动脚本.
  3. */
  4. publicstaticvoidevalScriptAsMainMethod(){
  5. String[]args=newString[]{"Zhangsan","10"};//main(String[]args)
  6. Bindingbinding=newBinding(args);
  7. GroovyShellshell=newGroovyShell(binding);
  8. shell.evaluate("staticvoidmain(String[]args){if(args.length!=2)return;println('Hello,Iam'+args[0]+',age'+args[1])}");
  9. shell=null;
  10. binding=null;
  11. }

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

Java代码收藏代码
  1. /**
  2. *运行完整脚本
  3. *@throwsException
  4. */
  5. publicstaticvoidevalScriptTextFull()throwsException{
  6. StringBufferbuffer=newStringBuffer();
  7. //defineAPI
  8. buffer.append("classUser{")
  9. .append("Stringname;Integerage;")
  10. //.append("User(Stringname,Integerage){this.name=name;this.age=age};")
  11. .append("StringsayHello(){return'Hello,Iam'+name+',age'+age;}}\n");
  12. //Usage
  13. buffer.append("defuser=newUser(name:'zhangsan',age:1);")
  14. .append("user.sayHello();");
  15. //groovy.lang.Binding
  16. Bindingbinding=newBinding();
  17. GroovyShellshell=newGroovyShell(binding);
  18. Stringmessage=(String)shell.evaluate(buffer.toString());
  19. System.out.println(message);
  20. //重写main方法,默认执行
  21. StringmainMethod="staticvoidmain(String[]args){defuser=newUser(name:'lisi',age:12);print(user.sayHello());}";
  22. shell.evaluate(mainMethod);
  23. shell=null;
  24. }

4) 方法执行和分部调用

Java代码收藏代码
  1. /**
  2. *以面向"过程"的方式运行脚本
  3. *@throwsException
  4. */
  5. publicstaticvoidevalScript()throwsException{
  6. Bindingbinding=newBinding();
  7. GroovyShellshell=newGroovyShell(binding);
  8. //直接方法调用
  9. //shell.parse(newFile(//))
  10. Scriptscript=shell.parse("defjoin(String[]list){returnlist.join('--');}");
  11. StringjoinString=(String)script.invokeMethod("join",newString[]{"A1","B2","C3"});
  12. System.out.println(joinString);
  13. ////脚本可以为任何格式,可以为main方法,也可以为普通方法
  14. //1)defcall(){...};call();
  15. //2)call(){...};
  16. script=shell.parse("staticvoidmain(String[]args){i=i*2;}");
  17. script.setProperty("i",newInteger(10));
  18. script.run();//运行,
  19. System.out.println(script.getProperty("i"));
  20. //thesameas
  21. System.out.println(script.getBinding().getVariable("i"));
  22. script=null;
  23. shell=null;
  24. }

二. GroovyClassLoader代码示例

1) 解析groovy文件

Java代码收藏代码
  1. /**
  2. *fromsourcefileof*.groovy
  3. */
  4. publicstaticvoidparse()throwsException{
  5. GroovyClassLoaderclassLoader=newGroovyClassLoader(Thread.currentThread().getContextClassLoader());
  6. FilesourceFile=newFile("D:\\TestGroovy.groovy");
  7. ClasstestGroovyClass=classLoader.parseClass(newGroovyCodeSource(sourceFile));
  8. GroovyObjectinstance=(GroovyObject)testGroovyClass.newInstance();//proxy
  9. Longtime=(Long)instance.invokeMethod("getTime",newDate());
  10. System.out.println(time);
  11. Datedate=(Date)instance.invokeMethod("getDate",time);
  12. System.out.println(date.getTime());
  13. //here
  14. instance=null;
  15. testGroovyClass=null;
  16. }

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

Java代码收藏代码
  1. publicstaticvoidload()throwsException{
  2. GroovyClassLoaderclassLoader=newGroovyClassLoader(Thread.currentThread().getContextClassLoader());
  3. BufferedInputStreambis=newBufferedInputStream(newFileInputStream("D:\\TestGroovy.class"));
  4. ByteArrayOutputStreambos=newByteArrayOutputStream();
  5. for(;;){
  6. inti=bis.read();
  7. if(i==-1){
  8. break;
  9. }
  10. bos.write(i);
  11. }
  12. ClasstestGroovyClass=classLoader.defineClass(null,bos.toByteArray());
  13. //instanceofproxy-class
  14. //ifinterfaceAPIisintheclasspath,youcandosuchas:
  15. //MyObjectinstance=(MyObject)testGroovyClass.newInstance()
  16. GroovyObjectinstance=(GroovyObject)testGroovyClass.newInstance();
  17. Longtime=(Long)instance.invokeMethod("getTime",newDate());
  18. System.out.println(time);
  19. Datedate=(Date)instance.invokeMethod("getDate",time);
  20. System.out.println(date.getTime());
  21. //here
  22. bis.close();
  23. bos.close();
  24. instance=null;
  25. testGroovyClass=null;
  26. }

三. ScriptEngine

1) pom.xml依赖

Xml代码收藏代码
  1. <dependency>
  2. <groupId>org.codehaus.groovy</groupId>
  3. <artifactId>groovy</artifactId>
  4. <version>2.1.6</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.codehaus.groovy</groupId>
  8. <artifactId>groovy-jsr223</artifactId>
  9. <version>2.1.6</version>
  10. </dependency>

2) 代码样例

Java代码收藏代码
  1. publicstaticvoidevalScript()throwsException{
  2. ScriptEngineManagerfactory=newScriptEngineManager();
  3. //每次生成一个engine实例
  4. ScriptEngineengine=factory.getEngineByName("groovy");
  5. System.out.println(engine.toString());
  6. assertengine!=null;
  7. //javax.script.Bindings
  8. Bindingsbinding=engine.createBindings();
  9. binding.put("date",newDate());
  10. //如果script文本来自文件,请首先获取文件内容
  11. engine.eval("defgetTime(){returndate.getTime();}",binding);
  12. engine.eval("defsayHello(name,age){return'Hello,Iam'+name+',age'+age;}");
  13. Longtime=(Long)((Invocable)engine).invokeFunction("getTime",null);
  14. System.out.println(time);
  15. Stringmessage=(String)((Invocable)engine).invokeFunction("sayHello","zhangsan",newInteger(12));
  16. System.out.println(message);
  17. }

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

关于ScriptEngine更多介绍,请参考.

分享到:
评论
1 楼 相约的旋律 2015-12-10  
能把代码弄整齐不?

相关推荐

    java在嵌入运行groovy代码1

    Java 嵌入运行 Groovy 代码是一种常见的技术实践,特别是在需要动态脚本执行或灵活扩展功能的场景中。Groovy 是一种与 Java 兼容的动态编程语言,它的语法简洁,适合编写脚本和快速原型开发。在 Java 应用程序中运行...

    java应用简单嵌入脚本模块

    压缩包中的`Groovy_Script`很可能包含了几个Groovy脚本文件,这些文件可能包含了示例代码,展示了如何在Java应用中嵌入Groovy脚本。文件名可能如`ScriptExample.groovy`,其中包含了具体的脚本代码,如定义函数、...

    java 动态脚本语言 精通 Groovy

    9. **Scripting in Java Applications**:Groovy可以嵌入到Java应用中作为脚本语言使用,例如在服务器端处理HTTP请求,或者作为配置文件来动态改变应用行为。 10. **持续集成与构建工具**:Groovy也是构建工具如...

    groovy脚本语言bin

    此外,Groovy还与Java无缝集成,可以调用所有Java库,并且Java代码也可以直接嵌入到Groovy脚本中。 总之,Groovy脚本语言bin提供的1.6.5版本是一个全面的开发包,旨在支持开发人员在JVM上快速开发、测试和部署...

    第 1 部分: 引入 Java 脚本 API

    这个API在Java 6版本中得到了显著增强,为开发者提供了在Java程序中嵌入和执行脚本引擎的能力,例如JavaScript、Groovy或Rhino等。通过Java脚本API,开发者可以利用脚本语言的灵活性和简洁性,同时保持Java的系统级...

    groovy脚本1

    Groovy是一种动态、灵活的编程语言,它与Java高度兼容并常常被用于简化Java开发,尤其是在脚本编写和...通过`GroovyClassLoader`和`GroovyShell`,开发者可以轻松地将Groovy代码嵌入到Java应用中,实现动态行为和交互。

    java脚本 快速学习

    JSAPI是Java平台标准版(Java SE)的一部分,它允许开发者在Java程序中嵌入并执行脚本语言。JSAPI通过提供ScriptEngine接口,使得开发者能够轻松地调用不同脚本引擎,如JavaScript、Groovy或Rhino,执行脚本代码。...

    groovy-all.jar-生成JasperReport所要包含的包

    5. 嵌入式脚本:由于`groovy-all.jar`的存在,你可以直接在Java应用中执行Groovy脚本,无需额外的配置或环境。 6. 极简的语法:Groovy的语法比Java更简洁,例如,不需要分号和大括号来结束语句和块。 对于...

    groovy-all-1.8.1.jar.zip

    随着Groovy的更新迭代,后续版本提供了更多特性,如GroovyShell、GroovyScriptEngine等,用于运行和解释Groovy脚本,以及 Grape(依赖管理) 和 GPars(并行和并发处理库)等实用工具。 在实际开发中,Groovy常用于...

    在* .docx文档中使用Groovy脚本

    通过阅读并实践"Using-Groovy-scriptlets-inside-a-docx-document.pdf"文档,你将能够掌握如何在Word文档中嵌入和运行Groovy脚本,从而提升你的文档处理体验。无论你是企业用户还是个人开发者,这个技巧都值得你学习...

    Groovy语法系列教程之字符串(三).pdf

    字符串插值允许在字符串中嵌入Groovy表达式,这些表达式在字符串被处理时会被计算并替换为相应的值。插值表达式由${}包围,也可以使用$前缀直接插入表达式。 7. **内插闭包表达式的特殊情况** 在特定情况下,...

    groovy 1.8.6

    此外,Groovy与Java完全兼容,可以无缝地与Java代码混合编写,这意味着你可以在同一个项目中使用Java类和Groovy脚本。 Groovy 1.8.6中的一些关键特性包括: 1. **动态类型**:Groovy默认采用动态类型,这意味着...

    java脚本编程

    - **使用Groovy脚本**:在Java程序中可以通过`groovy.lang.GroovyShell`或`groovy.lang.GroovyClassLoader`来执行Groovy脚本。 #### 六、总结 虽然“Java脚本编程”这个说法可能并不准确,但在Java中确实可以通过...

    groovy文档

    Groovy提供了多种运行方式,包括通过命令行使用`groovysh`或`groovy`命令执行脚本,或者使用`groovyc`编译器将Groovy脚本编译成Java字节码。此外,Groovy还集成了常见的构建工具如Ant和Maven,使得集成到现有的构建...

    groovy基础语法.pdf

    Groovy支持模块化编程,可以通过import语句导入其他Groovy脚本或Java类。同时,Groovy允许以脚本的形式运行代码,这意味着可以快速执行代码片段而无需编写完整的类和方法。 元编程: Groovy提供了强大的元编程能力...

    groovy入门经典,groovyeclipse 插件

    这使得Groovy成为快速开发、脚本编写以及构建自动化等任务的理想选择。 GroovyEclipse是一款强大的Eclipse插件,专门为Groovy开发者设计。它为Eclipse IDE带来了对Groovy语言的全面支持,包括语法高亮、代码提示、...

    groovy经典_资料

    Groovy是一种基于Java平台的动态脚本语言,它在设计时考虑了简洁性和生产力的提升。Groovy之所以受到青睐,主要是因为它比Java更加抽象和高效,允许开发者编写更少的代码来实现同样的功能。以下是对Groovy的一些核心...

    groovy初学者的福音

    4. **GroovyShell与GroovyScriptEngine**:这两个工具允许你在运行时执行Groovy代码,是学习和调试Groovy脚本的好帮手。 5. **GString与字符串操作**:Groovy的GString是一种可以包含表达式的字符串,它允许你在...

Global site tag (gtag.js) - Google Analytics