我有一个xml文件,包含groovy脚本文本,如下所示
<agent>
<request id=1>
<snippet>
import java.util.regex.Matcher;
import java.util.regex.Pattern;
pageText = "My Page Text";
</sniipet>
</request>
<request id=2>
<snippet>
Pattern matchlinkPat=Pattern.compile("callEvent",Pattern.MULTILINE);
Matcher match = matchlinkPat.matcher(pageText);
</sniipet>
</request>
</agent>
我正在评估来自我的Java类的<snippet>
标记中的字符串文本,如下所示
//Inside my Java Class
Binding binding = new Binding();
GroovyShell groovyshell = new GroovyShell(binding);
//Iterate each snippet tag and evaluate the script code
public Object evaluate(String code) {
return groovyshell.evaluate(code);
}
评估第一个代码段,但第二个代码段无法评估。
如果我重新声明第二个代码段中的导入,则会对其进行评估而不会出现任何错误。
有什么方法可以让我的导入可用于以下片段文本?
答案 0 :(得分:3)
不,这是不可能的,因为GroovyShell.evaluate(String script)
使用传递String的代码创建一个Groovy脚本类,然后运行它。
/**
* Evaluates some script against the current Binding and returns the result
*
* @param codeSource
* @throws CompilationFailedException
*/
public Object evaluate(GroovyCodeSource codeSource) throws CompilationFailedException {
Script script = parse(codeSource);
return script.run();
}
来源:https://github.com/groovy/groovy-core/blob/GROOVY_2_4_X/src/main/groovy/lang/GroovyShell.java#L590
每个脚本都是独立运行的,因此Groovy shell不会记录以前的评估所做的事情 - 每个脚本都以一个全新的脚本开始,带有绑定,您将构造函数参数传递给GroovyShell
类构造函数。这就是为什么你的导入永远不会出现在第二个片段中。基本上没有显式导入的第二个片段是没用的 - 在这种情况下,Groovy shell的行为正确。
您在评论中询问为什么第一个代码段中的pageText
在第二个代码段中可见。这是因为Groovy脚本使用bindings机制来存储和检索变量。 Groovy的Script
类以下列方式覆盖getProperty(String property)
和setProperty(String property, Object value)
方法:
public Object getProperty(String property) {
try {
return binding.getVariable(property);
} catch (MissingPropertyException e) {
return super.getProperty(property);
}
}
public void setProperty(String property, Object newValue) {
if ("binding".equals(property))
setBinding((Binding) newValue);
else if("metaClass".equals(property))
setMetaClass((MetaClass)newValue);
else
binding.setVariable(property, newValue);
}
来源:https://github.com/apache/groovy/blob/master/src/main/groovy/groovy/lang/Script.java#L54
正如您所看到的,当您尝试在Groovy脚本中访问变量或尝试为脚本中的变量赋值时,它会从bindings
对象中检索并存储此信息(您可以认为关于bindings
对象作为Map<String, Object>
)。并且因为您使用相同的GroovyShell
实例评估两个片段,所以两个脚本都使用相同的bindings
对象。这就是为什么第一个代码段中的pageText
存储在bindings
对象中的原因,当您在第二个代码段中使用此变量时,它会从bindings
得到解决而没有任何问题。