我需要创建一个 Freemarker 指令,将标签的“未处理”内容传递给 java 方法。目的是将默认模板片段加载到数据库中,以便可以通过另一个过程检查和编辑它们,然后输出编辑内容的结果(如果有)。我创建了一个宏,几乎可以做到这一点,问题是模板片段在传递给 java 方法之前已被处理。
这是我当前的代码:
<#macro process name>
<#local content><#nested/></#local>
${myjava.processContent(name, content)}
</#macro>
<@process 'this-content-name'><p>This is some content about ${companyName}</p></@process>
Java:
//Add and instance of this class to the Freemarker data model for use in templates.
public class MyJava {
public String processContent(String name, String content) {
log.debug("Data To Process: name = {}, content = {}", name, content);
String contentToOutput = getFromDb(name);
if(contentToOutput == null) {
insertContentInDb(name, content);
contentToOutput = content;
}
TemplateModel model = Environment.getCurrentEnvironment().getDataModel();
Configuration config = Environment.getCurrentEnvironment().getConfiguration();
Template template = new Template("template-from-content", contentToOutput, config);
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
}
}
运行上述命令时,我需要看到以下记录:
Data To Process: name = this-content-name, content = <p>This is some content about ${companyName}</p>
不幸的是我看到了这个:
Data To Process: name = this-content-name, content = <p>This is some content about My Company Name</p>
问题很明显,
<#nested/>
标签在存储在我的宏中的局部变量中之前由模板引擎处理。
查看 Freemarker 源代码,我发现
Environment
有 invokeNestedContent()
似乎可以处理宏的内容,并且似乎有用于检索标签的原始内容的方法,即
<p>This is some content about ${companyName}</p>
。不幸的是,这些方法具有包私有访问权限,并且无法从我的代码中访问。是否有另一种方法可以检索 Freemarker 中自定义指令的 RAW 未处理内容?这对于构建内容管理系统来说似乎是非常有用的功能。
这确实是一种相当不寻常的使用方式。为了提供一些上下文,理论上
#nested
Template
-s 实际上有一个
Template
方法(我宁愿将其视为历史文物,但无论如何它都会保留下来),所以即使它用于工具(和错误消息),信息也是如此在那里。因此,由于上述原因,您所做的标准方法是使用 getSource(col1, row1, col2, row2)
来阻止处理,尽管它有点过于冗长。但是,您还希望在以原始形式捕获嵌套内容后对其进行处理(执行),如果我看得很好的话(这很奇怪),这意味着您最好让 FreeMarker 将其与模板的其余部分一起解析。所以,我认为,你可以从 <@process 'foo'><#noparse>...</#noparse></@process>
开始(请参阅 JavaDoc-s;你可能需要使用
Environment.getCurrentDirectiveCallPlace
而不是 TemplateDirectiveModel
),这样你就有了源代码位置,然后使用
#macro
。我没试过,但我想这可以工作。