使用 GroovyShell 作为“表达式评估器/引擎” (或者:如何重用 GroovyShell)

发布于 2024-10-22 11:22:34 字数 951 浏览 1 评论 0 原文

我在程序中使用 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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

任谁 2024-10-29 11:22:34

您可以缓存 GroovyShell,无需总是创建一个新脚本:

final static GroovyShell shell = new 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:

final static GroovyShell shell = new GroovyShell()

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.

拥醉 2024-10-29 11:22:34

我想你可以避免每次构建一个完整的常规环境的负担。

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

作为示例,请参阅 groovy 网站中的此页面,解释如何启动Java 应用程序中使用 GroovyScriptEngineImpl 的 groovy 脚本

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

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

编辑一件重要的事情需要注意的是,GroovyScriptEngineImplGroovyShell 都不能保证任何类型的线程安全,因为任何 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

  • reuse your script engine
  • ensure your script evals in application context (eventually benefitting from Java objects usage)

EDIT one important thing to notice is that neither GroovyScriptEngineImpl nor GroovyShell 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).

压抑⊿情绪 2024-10-29 11:22:34

我最终这样做了:

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

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

为了安全起见,您可以将 shell 放入 ThreadLocal 或池中。

I end up doing this:

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

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

And just to be safe, you can put shell in ThreadLocal or pool.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文