Groovy脚本高级特征总结

简介: 合理的使用脚本特征功能,可以大大提高程序的灵活性,这非常适合做一些补丁功能,或者个性化极强的功能,比如促销活动,这个活动规则会经常的变动,因此,如果不借助某种机制,当促销规则发生变化时,则需要重新进行编码调整并发布程序,这样的程序维护起来过于麻烦。

       Groovy是一种基于JVM,功能强大、类型可选、动态的,可与Java无缝衔接的编程语言。该语言易于学习,可以大大提高开发人员的工作效率,可为Java程序添加强大的功能,其中就包含脚本功能(scripting capabilities。合理的使用脚本特征功能,可以大大提高程序的灵活性,这非常适合做一些补丁功能,或者个性化极强的功能,比如促销活动,这个活动规则会经常的变动,因此,如果不借助某种机制,当促销规则发生变化时,则需要重新进行编码调整并发布程序,这样的程序维护起来过于麻烦。
      针对类似促销规则多变的编程场景,用脚本引擎来实现规则的维护和运行,是一种很好的方案。由于脚本本质上就是一段文本代码,因此,可以非常方便的在后台进行及时的维护,当运行时,则加载并运行新脚本即可实现新促销方案的发布工作。本篇就重点对脚本特征进行介绍。

     根据官方的介绍,Groovy语言提供了多种机制,可以很好的与Java语言或者Groovy本身进行脚本特征的整合工作。官方的文档地址为:https://docs.groovy-lang.org ,可根据需要自行阅读相关文档进行学习。
    首先,在Groovy语言框架中,提供了一个groovy.util.Eval 类,可以动态的执行脚本,它的使用也非常的简单,其中有一个Eval.me方法,可执行脚本。下面给出示例代码:

importgroovy.util.Evaly=Eval.me('2.5 * 3')
printlny//7.5printlnEval.x(7, '2*x') // 14 printlnEval.xyz(3, 2, 6, 'x*y+z') //12printlnEval.me('m', 3, 'm**2') //9

    从示例代码中可知,首先需要导入包,然后就可以用Eval.me或者其他方法来实现简单的脚本执行。特别的,它支持动态参数功能,如一个表达式中参数x,y,z,那么可以使用Eval.xyz()方法来执行。

    注意:Eval类执行脚本是没有缓存功能的,且不适合处理多行的脚本。因此只适合于简单的脚本执行。

    其次,在Groovy语言框架中,还提供了一个groovy.lang.GroovyShell类,也可以动态的执行脚本,它可以对脚本进行缓存,并处理多种数据来源的脚本,如多行文本String,文件File,Reader和InputStream等。下面给出示例代码:

defshell=newGroovyShell()                           
defy=shell.evaluate'2.5 * 3'printlny// 7.5             y=shell.evaluate(newStringReader('2.5 * 3'))   
printlny// 7.5defscript=shell.parse'2.5 * 3'printlnscriptinstanceofgroovy.lang.Script//trueprintlnscript.run() // 7.5///////////////////////////defsharedData=newBinding()                          
defshell=newGroovyShell(sharedData)                 
sharedData.setProperty('name', 'Jack')     
sharedData.setProperty('age', 33)                     
//Jack age is 33printlnshell.evaluate('"$name age is $age"')  
shell.evaluate('x = 7')                               
printlnsharedData.getProperty('x') //7//显性类型,局部变量,无法外部访问shell.evaluate('int y = 7')                               
printlnsharedData.getProperty('y') //Exception//def局部变量,无法外部访问shell.evaluate('def z = 7')                               
printlnsharedData.getProperty('z') //Exception///////////////////////////defshell=newGroovyShell()                 
shell.evaluate('x = 7')                               
shell.evaluate('y = 2 * x') 
printlnshell.evaluate('"$y"') //14

     注意:共享变量是全局变量,多线程下是有点问题的,不是线程安全的。

     除此外,GroovyShell下还有一个parse方法也可以支持脚本特征,示例如下:

defshell=newGroovyShell()
defb1=newBinding(x:3)
defscript1=shell.parse('x = 2*x ; x = x + 1;def sum(x,y){return x+y};x = sum(x,1)')                    
script1.binding=b1script1.run()                      
printlnb1.getProperty('x') //8

  从示例中可知,它可以解析多条语句,用分号分隔,并支持函数定义等。

  其次,还有一种就是groovy.lang.GroovyClassLoader类,可以更加灵活的执行脚本,示例如下:

importgroovy.lang.GroovyClassLoaderdefcloader=newGroovyClassLoader()                                           
defclazz=cloader.parseClass('class Utils { void say(String msg) { println "Hello,"+msg } }')    
printlnclazz.name// Utils                                              defo=clazz.newInstance()                                                 
o.say("Jack") //Hello,Jack////////////////////////////importgroovy.lang.GroovyClassLoaderdefgcl=newGroovyClassLoader()
defclazz1=gcl.parseClass('class Utils { void say(String msg) { println "Hello,"+msg } }') 
defclazz2=gcl.parseClass('class Utils { void say(String msg) { println "Hello,"+msg } }') 
printlnclazz1==clazz2//false/////////////////////////////////////defclazz3=gcl.parseClass(newFile("K:\\Utils.groovy"))                               
defclazz4=gcl.parseClass(newFile("K:\\Utils.groovy"))                                   
printlnclazz3==clazz4//true

      注意:GroovyClassLoader默认会引用所有创建的类对象,且文本定义的类,即使是同名的,也是不同的对象,因此,同样的脚本,多次执行会创建多个对象,可能会导致内存泄漏。当采用File传入脚本后,Groovy可以缓存同一个文件脚本,并只创建同一个对象。

     最后,还有一个groovy.util.GroovyScriptEngine也可以支持脚本特征,它的功能更加的强大和灵活。它是建立在GroovyClassLoader类之上,可以处理类的依赖问题以及重加载的问题,即可以实现热更新功能。示例如下:

defbinding=newBinding()
defengine=newGroovyScriptEngine("K:\\")          
while (true) {
//Demo02.groovy 文件名不能和类名Demo一致,否则类重复defutils=engine.run('Demo02.groovy', binding)                   
printlnutils.say("Jack")                                                 
Thread.sleep(500)
}
//Demo02.groovyclassDemo {
Stringsay(Stringmsg) {
"Hello, $msg"//"Hello2, $msg"    }
}
newDemo()


相关文章
|
6月前
|
运维 Shell Python
第九章 Python自定义模块及导入方法
第九章 Python自定义模块及导入方法
|
6月前
|
机器学习/深度学习 JSON 自然语言处理
python自动化标注工具+自定义目标P图替换+深度学习大模型(代码+教程+告别手动标注)
python自动化标注工具+自定义目标P图替换+深度学习大模型(代码+教程+告别手动标注)
MindOpt APL建模语言自定小义函数的重要性和示例
在编程和建模语言中,函数是一段独立的、可重复使用的代码块,用于执行特定任务。在MindOpt APL中,自定义函数的使用非常重要,因为它们提高了建模过程的效率、可读性和灵活性。
|
Java 测试技术 Apache
JMeter与Python的多重交响:从入门到高级应用(上)
在性能测试领域,Apache JMeter已经成为测试专业人士的首选工具,用于模拟用户行为、测量响应时间、评估系统性能。但在某些情境下,为了满足特定需求,我们需要更多的灵活性,比如引入Python来进行特定操作或处理复杂逻辑。**”** Jython -----
JMeter与Python的多重交响:从入门到高级应用(上)
|
Java 测试技术 Apache
JMeter与Python的多重交响:从入门到高级应用(下)
在性能测试领域,Apache JMeter已经成为测试专业人士的首选工具,用于模拟用户行为、测量响应时间、评估系统性能。但在某些情境下,为了满足特定需求,我们需要更多的灵活性,比如引入Python来进行特定操作或处理复杂逻辑。。
JMeter与Python的多重交响:从入门到高级应用(下)
|
Java API Maven
第三章 Gradle构建脚本基础
从这章开始,会对Gradle有一个大概的介绍,帮助大家快速的入门Gradle。本章从整体构建脚本的角度介绍Gradle,什么是Settings文件,他有什么作用;什么是Build文件,它又有什么作用,我们可以新建多少Build文件。
173 0
第三章 Gradle构建脚本基础
|
数据采集 JSON JavaScript
浅析Python 实现一个自动化翻译和替换的工具
浅析Python 实现一个自动化翻译和替换的工具
267 0
|
Java API Android开发
Gradle2.0用户指南翻译——第十三章. 编写构建脚本
翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc本文翻译所在分支:https://github.com/msdx/gradledoc/tree/2.0 。
1464 0
下一篇
无影云桌面