如何保留来自评估的导入以使其可用于后续评估调用
How to preserve imports from evaluate to make it available for following evaluate calls
我有一个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 class 中 <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);
}
第一个代码片段得到评估,但第二个代码片段评估失败。
如果我在第二个片段中重新声明导入,它会在没有任何错误的情况下得到评估。
有什么方法可以使我的导入可用于以下片段文本?
不,这是不可能的,因为 GroovyShell.evaluate(String script)
使用您传递一个字符串的代码创建了一个 Groovy 脚本 class 然后它会运行它。
/**
* 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 不会记录之前的评估做了什么 - 每个脚本都是作为一个全新的脚本开始的,你将一个构造函数参数传递给 [=13] =] class 构造函数。这就是为什么您的导入从未出现在第二个片段中的原因。基本上没有显式导入的第二个片段是无用的 - Groovy shell 在这种情况下表现正确。
Groovy 脚本绑定
您在评论中询问了为什么第一个片段中的 pageText
在第二个片段中可见。这是因为 Groovy 脚本使用 bindings 机制来存储和检索变量。 Groovy 的 Script
class 按以下方式覆盖 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 脚本中的变量或尝试为脚本中的变量赋值时,它都会从 [=18= 中检索并存储此信息] 对象(您可以将 bindings
对象视为 Map<String, Object>
)。因为您使用相同的 GroovyShell
实例评估两个片段,所以两个脚本都使用相同的 bindings
对象。这就是为什么第一个代码段中的 pageText
存储在 bindings
对象中,当您在第二个代码段中使用此变量时,它会从 bindings
中毫无问题地解析。
我有一个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 class 中 <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);
}
第一个代码片段得到评估,但第二个代码片段评估失败。
如果我在第二个片段中重新声明导入,它会在没有任何错误的情况下得到评估。
有什么方法可以使我的导入可用于以下片段文本?
不,这是不可能的,因为 GroovyShell.evaluate(String script)
使用您传递一个字符串的代码创建了一个 Groovy 脚本 class 然后它会运行它。
/**
* 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 不会记录之前的评估做了什么 - 每个脚本都是作为一个全新的脚本开始的,你将一个构造函数参数传递给 [=13] =] class 构造函数。这就是为什么您的导入从未出现在第二个片段中的原因。基本上没有显式导入的第二个片段是无用的 - Groovy shell 在这种情况下表现正确。
Groovy 脚本绑定
您在评论中询问了为什么第一个片段中的 pageText
在第二个片段中可见。这是因为 Groovy 脚本使用 bindings 机制来存储和检索变量。 Groovy 的 Script
class 按以下方式覆盖 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 脚本中的变量或尝试为脚本中的变量赋值时,它都会从 [=18= 中检索并存储此信息] 对象(您可以将 bindings
对象视为 Map<String, Object>
)。因为您使用相同的 GroovyShell
实例评估两个片段,所以两个脚本都使用相同的 bindings
对象。这就是为什么第一个代码段中的 pageText
存储在 bindings
对象中,当您在第二个代码段中使用此变量时,它会从 bindings
中毫无问题地解析。