我在程序中使用 GroovyShell
作为“表达式求值器/引擎”。它接受两个输入:(a) 一个或多个初始化脚本 (b) 用户定义的脚本。然后,两者在运行时作为大块脚本(文本)连接起来并提供给 shell。
String initScripts = getFromDB()
String userScript = getFromUser()
def shell = new GroovyShell()
output = shell.evaluate(initScripts + userScript)
上面的代码将在循环中运行,其中 userScript
的内容会有所不同。
到目前为止,initScripts
仅包含可能在 userScript< 中引用的变量定义(例如 def $yyyy = new Date().format('yyyy')
) /code>(例如打印“$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"
}
这可能吗? (上次我用谷歌搜索这是不可能的,但我希望我错了)
I'm using GroovyShell
as an "expression evaluator/engine" inside my program. It accepts two inputs: (a) one or more init scripts (b) user-defined script. Both are then concatenated at runtime as big chunk of script (text) and feed to the shell.
String initScripts = getFromDB()
String userScript = getFromUser()
def shell = new GroovyShell()
output = shell.evaluate(initScripts + userScript)
The above code will run in a loop, where the contents of userScript
will vary.
So far, initScripts
only contain variable definitions (e.g. def $yyyy = new Date().format('yyyy')
) which might be referenced in userScript
(e.g. print "$yyyy 001"
).
Is there any more efficient approach for this? (E.g. reusing the shell, how?) Because right now it's very slow.
Edit: Groovy is a must. Please don't recommend other scripting engine.
Edit: I'm thinking whether GroovyShell can do this (pseudo-code):
def shell = new GroovyShell()
shell.evaluate(initScripts)
for each userScript in DB {
shell.put(userScript )
def result = shell.evaluateThat()
println "Result is $result"
}
Is this possible? (Last time I googled it's not possible, but I'm hoping I'm wrong)
发布评论
评论(3)
您可以缓存 GroovyShell,无需总是创建一个新脚本:
此外,如果您多次运行一个脚本,您也可以缓存它们。您可以使用 Script “nofollow">GroovyShell.parse(String scriptText),使用 Script.run() 运行脚本。
文档的这一部分可能也会有所帮助,您还可以动态创建 Groovy 对象,而不是脚本。
You can cache the GroovyShell, you don't need to create a new one always:
Also if you run one Script many times you may cache them too. You can create a
Script
with GroovyShell.parse(String scriptText), use Script.run() to run the script.This section of the documentation might help too, instead of scripts you can also create groovy objects dynamically.
我想你可以避免每次构建一个完整的常规环境的负担。
从 Java 6 开始,Java 中提供了脚本 API 支持,它允许您使用轻量级脚本引擎。
作为示例,请参阅 groovy 网站中的此页面,解释如何启动Java 应用程序中使用
GroovyScriptEngineImpl
的 groovy 脚本。请注意,您可能会失去一些 groovy 的优点,例如 Groovy 葡萄,但您将能够
编辑一件重要的事情需要注意的是,
GroovyScriptEngineImpl
和GroovyShell
都不能保证任何类型的线程安全,因为任何 Groovy 脚本都可以自由生成任意数量的线程。事实上,保证线程安全的唯一方法是安装 SecurityManager 禁止线程操作。事实上,即使这样也不能保证线程安全(因为只有确保所有 Java 代码库都是线程安全的,才能实现线程安全)。I guess you could avoid the weight of building a full groovy environment each time.
Since Java 6, there is a scripting API support in Java, which allows you to use lightweight scripting engines.
As an example, see this page in groovy website explaining how to start a groovy script in a Java application using
GroovyScriptEngineImpl
.notice you may loose some groovy goodnesses, like maybe Groovy grape, but you'll be able to
EDIT one important thing to notice is that neither
GroovyScriptEngineImpl
norGroovyShell
can guarantee you any kind of thread safety, as any groovy script is free to spawn any number of thread. In fact, the only way you could guarantte thread safety would be by installing a SecurityManager forbidding thread operations. In fact, even that wouldn't guarantee thread safety (as this thread safety could only be achieved by ensuring all your Java code base is thread safe).我最终这样做了:
为了安全起见,您可以将
shell
放入ThreadLocal
或池中。I end up doing this:
And just to be safe, you can put
shell
inThreadLocal
or pool.