使用grovyshell作为“表达评估器/发动机”(OR:如何重复使用grovyshell)

StackOverflow https://stackoverflow.com/questions/5323114

  •  24-10-2019
  •  | 
  •  

我在用着 GroovyShell 作为我程序内部的“表达评估器/引擎”。它接受两个输入:(a)一个或多个初始脚本(b)用户定义的脚本。然后,两者在运行时将两者串联成大块的脚本(文本),然后馈送到外壳。

String initScripts = getFromDB()
String userScript = getFromUser()

def shell = new GroovyShell()
output = shell.evaluate(initScripts + userScript)

以上代码将以循环运行,其中内容的内容 userScript 会有所不同。

至今, initScripts 仅包含可变定义(例如 def $yyyy = new Date().format('yyyy'))可能在 userScript (例如 print "$yyyy 001").

有什么更有效的方法吗? (例如,重用外壳,如何?),因为现在是 非常 减缓。

编辑: Groovy是必须的。请不要推荐其他脚本引擎。

编辑: 我在想GROOVYSHELL是否可以这样做(伪代码):

def shell = new GroovyShell()
shell.evaluate(initScripts)

for each userScript in DB {
    shell.put(userScript )
    def result = shell.evaluateThat()
    println "Result is $result"
}

这可能吗? (上次我谷歌搜索不可能,但我希望我错了)

有帮助吗?

解决方案

您可以缓存Grovyshell,您无需始终创建一个新的:

final static GroovyShell shell = new GroovyShell()

另外,如果您多次运行一个脚本,也可以缓存它们。您可以创建一个 Scriptgroovyshell.parse(字符串scripttext), , 利用 script.run() 运行脚本。

本节 文档也可能会有所帮助,而不是脚本,您也可以动态创建Groovy对象。

其他提示

我想您可以避免每次建立一个完整的槽环境的重量。

自Java 6以来,Java中有脚本API支持,可让您使用轻质的脚本引擎。

例如,请参阅 此页面在Groovy网站上 解释如何使用Java应用程序启动Groovy脚本 GroovyScriptEngineImpl.

请注意,您可能会失去一些令人讨厌的美感,例如Groovy Grape,但您将能够

  • 重复使用脚本引擎
  • 确保您的脚本在应用程序上下文中的流动(最终从Java对象使用中受益)

编辑 要注意的一件重要的事情是 GroovyScriptEngineImpl 也不 GroovyShell 可以保证您任何类型的线程安全性,因为任何Groovy脚本都可以免费产生任何数量的线程。实际上,您可以保证线程安全的唯一方法就是 安装安全管理器 禁止线程操作。实际上,即使这样,也不能保证线程安全性(因为只有通过确保所有Java代码基库都安全,才能实现此线程安全)。

我最终这样做:

def shell = new GroovyShell()
shell.evaluate(initScripts)

for( i in 1..count )
{
    output = shell.evaluate(userScripts);
}

为了安全起见,你可以说 shellThreadLocal 或游泳池。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top