9

GroovyShell在我的程序中用作“表达式评估器/引擎”。它接受两个输入:(a) 一个或多个初始化脚本 (b) 用户定义的脚本。然后在运行时将两者连接为一大块脚本(文本)并提供给 shell。

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

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

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

到目前为止,仅包含可能在(例如)中引用的initScripts变量定义(例如)。def $yyyy = new Date().format('yyyy')userScriptprint "$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"
}

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

4

3 回答 3

7

你可以缓存 GroovyShell,你不需要总是创建一个新的:

final static GroovyShell shell = new GroovyShell()

此外,如果您多次运行一个脚本,您也可以缓存它们。您可以Script使用GroovyShell.parse(String scriptText)创建一个,使用Script.run()运行脚本。

文档的这一部分也可能会有所帮助,除了脚本之外,您还可以动态创建 groovy 对象。

于 2011-03-16T19:25:03.977 回答
1

我想你可以避免每次都构建一个完整的 groovy 环境的重量。

从 Java 6 开始,Java 中有一个脚本 API 支持,它允许您使用轻量级脚本引擎。

例如,请参阅groovy 网站中的此页面,解释如何在 Java 应用程序中使用GroovyScriptEngineImpl.

请注意,您可能会失去一些 groovy 的优点,比如 Groovy 葡萄,但您将能够

  • 重用你的脚本引擎
  • 确保您的脚本在应用程序上下文中进行评估(最终受益于 Java 对象的使用)

编辑需要注意的一件重要事情是,既GroovyScriptEngineImpl不能也GroovyShell不能保证任何类型的线程安全,因为任何 groovy 脚本都可以自由生成任意数量的线程。事实上,保证线程安全的唯一方法是安装一个 SecurityManager禁止线程操作。事实上,即使这样也不能保证线程安全(因为这种线程安全只能通过确保所有 Java 代码库都是线程安全的来实现)。

于 2011-03-16T09:29:40.623 回答
0

我最终这样做:

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

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

为了安全起见,您可以放入shellThreadLocal池中。

于 2011-03-17T06:09:26.043 回答