我完全不确定这是否是一个可解决的问题,但假设我有一个freemarker模板,我希望能够向模板询问它使用的变量.
出于我的目的,我们可以假设freemarker模板非常简单 - 只是"根级"条目(这种模板的模型可以是一个简单的Map).换句话说,我不需要处理调用嵌套结构等的模板.
从java获取变量的另一种方法。这只是尝试处理模板并捕获InvalidReferenceException以查找 freemarker-template 中的所有变量
/**
* Find all the variables used in the Freemarker Template
* @param templateName
* @return
*/
public Set<String> getTemplateVariables(String templateName) {
Template template = getTemplate(templateName);
StringWriter stringWriter = new StringWriter();
Map<String, Object> dataModel = new HashMap<>();
boolean exceptionCaught;
do {
exceptionCaught = false;
try {
template.process(dataModel, stringWriter);
} catch (InvalidReferenceException e) {
exceptionCaught = true;
dataModel.put(e.getBlamedExpressionString(), "");
} catch (IOException | TemplateException e) {
throw new IllegalStateException("Failed to Load Template: " + templateName, e);
}
} while (exceptionCaught);
return dataModel.keySet();
}
private Template getTemplate(String templateName) {
try {
return configuration.getTemplate(templateName);
} catch (IOException e) {
throw new IllegalStateException("Failed to Load Template: " + templateName, e);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
这可能是迟到的,但是如果其他人遇到这个问题:您可以使用'data_model'和'globals'来检查模型 - data_model将只包含模型提供的值,而globals也将包含模板中定义的任何变量.你需要在点前加上特殊变量 - 所以要访问全局变量,请使用$ {.globals}
有关其他特殊变量,请参阅http://freemarker.sourceforge.net/docs/ref_specvar.html
我有同样的任务从 java 端的模板获取变量列表,但除了使用反射之外,没有找到任何好的方法。我不确定是否有更好的方法来获取这些数据,但这是我的方法:
public Set<String> referenceSet(Template template) throws TemplateModelException {
Set<String> result = new HashSet<>();
TemplateElement rootTreeNode = template.getRootTreeNode();
for (int i = 0; i < rootTreeNode.getChildCount(); i++) {
TemplateModel templateModel = rootTreeNode.getChildNodes().get(i);
if (!(templateModel instanceof StringModel)) {
continue;
}
Object wrappedObject = ((StringModel) templateModel).getWrappedObject();
if (!"DollarVariable".equals(wrappedObject.getClass().getSimpleName())) {
continue;
}
try {
Object expression = getInternalState(wrappedObject, "expression");
switch (expression.getClass().getSimpleName()) {
case "Identifier":
result.add(getInternalState(expression, "name").toString());
break;
case "DefaultToExpression":
result.add(getInternalState(expression, "lho").toString());
break;
case "BuiltinVariable":
break;
default:
throw new IllegalStateException("Unable to introspect variable");
}
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new TemplateModelException("Unable to reflect template model");
}
}
return result;
}
private Object getInternalState(Object o, String fieldName) throws NoSuchFieldException, IllegalAccessException {
Field field = o.getClass().getDeclaredField(fieldName);
boolean wasAccessible = field.isAccessible();
try {
field.setAccessible(true);
return field.get(o);
} finally {
field.setAccessible(wasAccessible);
}
}
Run Code Online (Sandbox Code Playgroud)
我为演示模板自省而制作的示例项目可以在 github 上找到: https: //github.com/SimY4/TemplatesPOC.git
| 归档时间: |
|
| 查看次数: |
6480 次 |
| 最近记录: |