我在程序中使用GroovyShell
作为“表达式评估程序/引擎”。它接受两个输入:(a)一个或多个init脚本(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')
中引用的变量定义(例如userScript
)(例如print "$yyyy 001"
)。
有没有更有效的方法呢? (例如,重用shell,怎么样?)因为现在它非常慢。
编辑: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"
}
这可能吗? (上次我用谷歌搜索它是不可能的,但我希望我错了)
答案 0 :(得分:7)
您可以缓存GroovyShell,您无需始终创建新的
final static GroovyShell shell = new GroovyShell()
此外,如果您多次运行一个脚本,也可以缓存它们。您可以使用GroovyShell.parse(String scriptText)创建Script
,使用Script.run()运行该脚本。
This section文档也可能有所帮助,您也可以动态创建groovy对象而不是脚本。
答案 1 :(得分:1)
我想你可以避免每次都建立一个完整的groovy环境的重量。
从Java 6开始,Java中有一个脚本API支持,允许您使用轻量级脚本引擎。
作为示例,请参阅this page in groovy website,了解如何使用GroovyScriptEngineImpl
在Java应用程序中启动groovy脚本。
注意你可能会失去一些时髦的善意,比如Groovy葡萄,但你能够
编辑需要注意的一点是,GroovyScriptEngineImpl
和GroovyShell
都不能保证任何线程的安全性,因为任何groovy脚本都可以自由地生成任意数量的线。实际上,保证线程安全的唯一方法是installing a SecurityManager禁止线程操作。实际上,即使这样也不能保证线程安全(因为只有通过确保所有Java代码库都是线程安全的才能实现此线程安全性。)
答案 2 :(得分:0)
我最终这样做了:
def shell = new GroovyShell()
shell.evaluate(initScripts)
for( i in 1..count )
{
output = shell.evaluate(userScripts);
}
为了安全起见,您可以将shell
放入ThreadLocal
或池中。