动态加载Groovy脚本到app服务器

时间:2014-11-14 18:58:57

标签: java spring tomcat groovy

我有一个在Tomcat中运行的Java Spring应用程序,用于根据传入的文件执行各种处理规则。由于文件类型和规则发生了变化,我想使用Groovy动态加载新的/更改的功能,而不必每次都重新编译/重新启动Java应用程序。

从Groovy documentation开始“在Java中动态加载并运行Groovy代码”,

GroovyClassLoader gcl = new GroovyClassLoader();
Class clazz = gcl.parseClass(myStringwithGroovyClassSource, "SomeName.groovy");
Object aScript = clazz.newInstance();
MyInterface myObject = (MyInterface) aScript;
myObject.interfaceMethod();

我创建了我的SomeName.groovy版本,它实现了MyInterface并修改了我的Java应用程序,然后创建了该类的实例,如上所示。我知道正在正确读取我的Groovy文件,因为如果我打印出myObject.getClass()。toString,它会显示SomeName.groovy中定义的正确对象类型;但是,当它调用其中一个实现的方法(myObject.interfaceMethod())时,它什么都不做。

我已经在Tomcat之外的Java应用程序中测试了这种方法,但它确实有效,所以我不确定为什么在app服务器内运行它会导致它崩溃。另外,我已经确认groovy-all-2.1.8.jar包含在我的项目中。

提前感谢您提供的任何信息,这些信息可能会说明动态加载可能失败的原因。

THX。

1 个答案:

答案 0 :(得分:3)

您正在使用的parseClass()方法的形式根本不会查看任何外部文件。相反,它会处理第一个String参数(在您的情况下为myStringwithGroovyClassSource,就好像它是Groovy源文件的文本内容,以及第二个String参数(在您的情况下为文字"SomeName.groovy",就像它是该文件的名称一样。此方法根本不会打开或解析任何 ACTUAL 文件。

要使此代码正常工作,您必须预定义变量myStringwithGroovyClassSource。整体效果看起来像这样:

def myStringwithGroovyClassSource = """
class SomeName implements MyInterface {
    def prop1 = 1, prop2 = 2
    def interfaceMethod() { println prop1 }
}
"""

interface MyInterface { def interfaceMethod() }
GroovyClassLoader gcl = new GroovyClassLoader()
Class clazz = gcl.parseClass(myStringwithGroovyClassSource, "SomeName.groovy")
Object aScript = clazz.newInstance()
MyInterface myObject = (MyInterface) aScript
myObject.interfaceMethod()

现在,另一方面,正如您所说,如果您已经有一个名为SomeFile.groovy的外部未编译的Groovy源文件,您希望通过GroovyClassLoader将其带入您的脚本,那么您需要更改现有的代码如下:

interface MyInterface { def interfaceMethod() }
GroovyClassLoader gcl = new GroovyClassLoader()
Class clazz = gcl.parseClass("SomeName.groovy" as File)
Object aScript = clazz.newInstance()
MyInterface myObject = (MyInterface) aScript
myObject.interfaceMethod()

如果文件中的代码在编译时是有效的,那么你应该没有问题。