Java 获取速度中的变量
我有一个插件项目,我正在使用Velocity模板。用户可以从首选项页面更改模板主体,我希望在用户单击首选项页面中的“确定”时获取模板主体中的变量。我需要帮助才能从Velocity模板正文中提取变量。我唯一能想到的方法是向Velocity引擎中添加如下内容:Java 获取速度中的变量,java,velocity,Java,Velocity,我有一个插件项目,我正在使用Velocity模板。用户可以从首选项页面更改模板主体,我希望在用户单击首选项页面中的“确定”时获取模板主体中的变量。我需要帮助才能从Velocity模板正文中提取变量。我唯一能想到的方法是向Velocity引擎中添加如下内容: VelocityContext context = new VelocityContext(); context.put("parameters", new HashMap()); 。。。在模板中,让用户将值放入参数hashmap,如下所示
VelocityContext context = new VelocityContext();
context.put("parameters", new HashMap());
。。。在模板中,让用户将值放入参数hashmap,如下所示:
#set ($t = $parameters.put("value", "key"))
(重要提示:用户必须为临时参数指定一个值,例如$t)
。。。然后,在渲染后,取出值:
HashMap map = (HashMap)context.get("parameters");
for (String key : map.keySet()) {
// ...
}
Velocity使用JavaCC解析模板并创建AST RuntimeInstance是解析模板所需的全部内容
RuntimeInstance ri = new RuntimeInstance();
SimpleNode node = ri.parse( reader, "templateName" );
现在,您必须根据需要扩展BaseVisitor。
BaseVisitor是所有访问者的抽象类。
BaseVisitor有一个用于节点类型的方法,因此您可以轻松筛选AST节点
ParserVisitor visitor = new BaseVisitor() {
@Override
public Object visit(final ASTReference node, final Object data) {
//insert here your logic ...
System.out.println(node.getFirstToken();
//use super.visit( node, data) if you need to traverse all node children
return null;
}
};
然后访问节点
visitor.visit(node, null);
如果您有以下模板:
some text $var other text
some text $var other text
#set( $primate = "monkey" )
建议只打印代码$var
请注意,asreference是任何引用。如果您有以下模板:
some text $var other text
some text $var other text
#set( $primate = "monkey" )
这段代码打印出来:$var
和$primate
项目完成了这项工作
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>xdocreport</artifactId>
<version>1.0.6</version>
</dependency>
StringReader templateReader = new StringReader(stringyTemplateContent);
FieldsExtractor<FieldExtractor> extractor = FieldsExtractor.create();
VelocityFieldsExtractor.getInstance().extractFields(templateReader, templateName, extractor);
for (FieldExtractor fieldExtractor : extractor.getFields()) {
System.out.println(fieldExtractor.getName());
}
fr.opensagres.xdocreport
举个例子 我通过注册一个用于存储实例的事件,然后使用盒带中的事件评估模板来实现。这并不是100%防弹的,因为引用可以包含很多内容,但我还没有看到一个明确的例子说明它失败了
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.event.EventCartridge;
import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class TemplateAnalyzer{
public static Set<String> getReferences(String template){
HashSet<String> names = new HashSet<>();
VelocityContext velocityContext = new VelocityContext();
EventCartridge ec = new EventCartridge();
ec.addEventHandler((ReferenceInsertionEventHandler)
(reference, value) -> names.add(reference)
);
ec.attachToContext(velocityContext);
Velocity.evaluate(velocityContext, new StringWriter(), "velocity", template);
return names;
}
private static Pattern namePattern = Pattern.compile("\\$!?\\{?([a-zA-Z][\\w*\\-])");
public static Set<String> getVariableNames(String template)
{
Set<String> references = getReferences(template);
return references.stream()
.map(r -> namePattern.matcher(r))
.filter(Matcher::find)
.map(m -> m.group(1))
.collect(Collectors.toSet());
}
}
import org.apache.velocity.VelocityContext;
导入org.apache.velocity.app.velocity;
导入org.apache.velocity.app.event.EventCartridge;
导入org.apache.velocity.app.event.ReferenceInsertionEventHandler;
导入java.io.StringWriter;
导入java.util.HashSet;
导入java.util.Set;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
导入java.util.stream.collector;
公共类模板分析器{
公共静态集getReferences(字符串模板){
HashSet name=新的HashSet();
VelocityContext VelocityContext=新的VelocityContext();
EventCartridge ec=新的EventCartridge();
ec.添加的事件处理程序((参考添加的事件处理程序)
(引用,值)->names.add(引用)
);
ec.attachToContext(velocityContext);
evaluate(velocityContext,new StringWriter(),“Velocity”,模板);
返回姓名;
}
私有静态模式namePattern=Pattern.compile(\\$!?\\{?([a-zA-Z][\\w*\\-]);
公共静态集getVariableNames(字符串模板)
{
Set references=getReferences(模板);
返回references.stream()
.map(r->namePattern.matcher(r))
.filter(匹配器::查找)
.map(m->m.group(1))
.collect(收集器.toSet());
}
}
您需要第二种方法来过滤掉任何不是简单变量的内容,并清理美元符号和大括号。“ec.addEventHandler((ReferenceInsertionEventHandler)(reference,value)->names.add(reference));”===>names.add返回布尔值,但需要对象。您能修复代码吗??