我有一个在 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();
我创建了实现 MyInterface 的 SomeName.groovy 版本,并修改了我的 Java 应用程序以创建该类的实例,如上所示。我知道我的 Groovy 文件被正确读取了,因为如果我打印出 myObject.getClass().toString,它会显示 SomeName.groovy 中定义的正确对象类型;然而,当它调用已实现的方法之一 (myObject.interfaceMethod()) 时,它什么都不做。
我已经在 Tomcat 之外的 Java 应用程序中测试了这种方法并且它有效,所以我不确定为什么在应用程序服务器内部运行它会导致它中断。此外,我已经确认 groovy-all-2.1.8.jar 包含在我的项目中。
提前感谢您提供的任何信息,这些信息可能会阐明动态加载失败的原因。
谢谢。
最佳答案
您使用的 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()
如果文件中的代码在编译时是有效的,那么你应该可以毫无问题地让它工作。
关于java - 将 Groovy 脚本动态加载到应用服务器中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26937029/