【问题标题】:Compiling user entered groovy script at run time编译用户在运行时输入 groovy 脚本
【发布时间】:2015-08-24 05:19:56
【问题描述】:

有一个场景如下,我需要验证 groovy 脚本的正确性。

class CostCalculator{

String name
String groovyScript

static constraints = {
groovyScript:static validateScript = {String script ,def obj->
        boolean status = true
        try {
            def shell = new GroovyShell()
            def data = shell.parse(script)
            data.run()
        }catch (Throwable e){
            e.printStackTrace()
            status = false
        }
        if(!status){
            return "domain.script.compilation.errors"
        }else{
            return true
        }
    }
}

}

上面代码的问题是它运行代码,如果有任何异常,它会在运行时抛出它。

有几件事情需要考虑:

  1. groovy 代码应该编译而不是运行(因为代码可能包含数据库级别更新)并抛出异常。
  2. groovy 代码应该静态编译,例如,如果我们在脚本中缺少某些属性,那么它必须得到通知。

下面可能是示例脚本:

void addCost(int x, int y,String itemName){
double cost = x*y + originalCost
Item item = SoldItem.findByItemName(itemName)
item.price += cost
}

【问题讨论】:

    标签: grails groovy


    【解决方案1】:

    我建议将您的 groovy 脚本放在一个类中。

    在示例中,您有方法 addCost(),所以我想说只是将此方法包装在一个类中。例如:

    String gScript = """
    class CostCalculatorScript{
        void addCost(int x, int y,String itemName){
            double cost = x*y + originalCost
            Item item = SoldItem.findByItemName(itemName)
            item.price += cost
        }
    }
    
    """
    

    现在使用 GroovyClassLoader 加载和解析这个脚本。

    ClassLoader gcl = new GroovyClassLoader()
    Class clazz = gcl.parseClass(gScript)
    

    验证加载的类是否与您在脚本中指定的名称相同。

    assert clazz.simpleName == 'CostCalculatorScript'
    

    现在您想要的解决方案看起来确实像静态编译。您可以将 @groovy.transform.CompileStatic 注释添加到您的类中。但是这个注解的问题是你不能使用 grails 的动态查找器或 def 关键字。

    但如果您仍然需要该功能,那么您应该使用 Grails 2.4 中提供的 @grails.compiler.GrailsCompileStatic 注释。

    【讨论】:

    • 我可以使用 def 除非在任何操作类型不安全的情况下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多