gpt4 book ai didi

java - 从持久的 Groovy 代码返回值而不使用 java.io.File

转载 作者:行者123 更新时间:2023-12-02 01:23:41 26 4
gpt4 key购买 nike

在我的最终产品中,我提供了使用小型 Groovy 脚本在运行时扩展应用程序代码的能力,这些脚本通过表单进行编辑,并且其代码保留在 SQL 数据库中。

这些“自定义代码”片段遵循的方案通常是根据输入参数返回一个值。例如,在服务开具发票期间,评级系统可能会通过自定义 Groovy 代码使用已发布的预定费率表或应用程序中的契约(Contract)中定义的值,如果返回“覆盖”值,则应该使用过。

在确定速率“覆盖”值的逻辑中,我合并了类似这些返回值的常规代码片段,或者如果它们返回 null,则使用默认值。例如

class GroovyRunner {

static final GroovyClassLoader classLoader = new GroovyClassLoader()
static final String GROOVY_CODE = MyDatabase().loadCustomCode()
static final String GROOVY_CLASS = MyDatabase().loadCustomClassName()
static final String TEMPDIR = System.getProperty("java.io.tmpdir")

double getOverrideRate(Object inParameters) {
def file = new File(TEMPDIR+GROOVY_CLASS+".groovy")

BufferedWriter bw = new BufferedWriter(new FileWriter(file))
bw.write(GROOVY_CODE)
bw.close()

Class gvy = classLoader.parseClass(file)
GroovyObject obj = (GroovyObject) gvy.getDeclaredConstructor().newInstance()
return Double.valueOf(obj.invokeMethod("getRate",inParameters)
}
}

然后,在用户创建的自定义 Groovy 代码中:

 class RateInterceptor {
def getRate(Object inParameters) {
def businessEntity = (SomeClass) inParameters

return businessEntity.getDiscount() == .5 ? .5 : null
}
}

问题在于,上面的 GROOVY_CODE 中的这些“自定义代码”位是在运行时从数据库中提取的,并且包含一个复杂的 groovy 类。由于该方法将被连续调用多次,因此每次运行时都创建一个新的 File 对象是不切实际的。

无论我使用 GroovyScriptEngine 还是 GroovyClassLoader,这些都需要 java.io.File 对象。这使得代码执行速度极其缓慢,因为必须在从数据库检索自定义 Groovy 代码后创建文件。有没有办法运行常规代码,可以返回一个值,而无需创建临时文件来执行它?

最佳答案

针对您的情况的直接解决方案是使用 GroovyClassLoader.parseClass​(String text)

http://docs.groovy-lang.org/latest/html/api/groovy/lang/GroovyClassLoader.html#parseClass(java.lang.String)

类缓存不应该成为问题,因为每次都会创建一个新的 GroovyClassLoader

<小时/>

但是考虑使用groovy脚本而不是类

您的速率拦截器代码可能如下所示:

def businessEntity = (SomeClass) context
return businessEntity.getDiscount() == .5 ? .5 : null

或者甚至像这样:

context.getDiscount() == .5 ? .5 : null

在脚本中你可以声明函数、内部类等

所以,如果您需要以下脚本也可以工作:

class RateInterceptor {
def getRate(SomeClass businessEntity) {
return businessEntity.getDiscount() == .5 ? .5 : null
}
}

return new RateInterceptor().getRate(context)

执行这些脚本的java代码:

import groovy.lang.*;
...

GroovyShell gs = new GroovyShell();
Script script = gs.parse(GROOVY_CODE);
// bind variables
Binding binding = new Binding();
binding.setVariable("context", inParams);
script.setBinding(binding);
// run script
Object ret = script.run();
<小时/>

请注意,groovy 代码(类或脚本)的解析是一项繁重的操作。如果您需要加速代码,请考虑将解析的类缓存到内存中的缓存中,甚至缓存到映射中

Map<String, Class<groovy.lang.Script>>

关于java - 从持久的 Groovy 代码返回值而不使用 java.io.File,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57279909/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com