如何处理 Freemarker 字符串模板?

Posted

技术标签:

【中文标题】如何处理 Freemarker 字符串模板?【英文标题】:How to process Freemarker String template? 【发布时间】:2018-05-02 17:48:59 【问题描述】:

我正在使用带有 Freemarker 启动器的 Spring Boot。

给定以下字符串:

<h2>$fragment.title</h2>

我正在尝试对此字符串执行一些验证,以确保它包含正确的 Freemarker 语法。

我已尝试使用以下代码执行此操作:

@Autowired
private Configuration configuration;

private void validateTemplate(Fragment fragment) 

    try 

        ModelAndView model = new ModelAndView();
        model.addObject("fragment", fragment);

        StringTemplateLoader stringLoader = new StringTemplateLoader();
        stringLoader.putTemplate("template", fragment.getDesign());

        configuration.setTemplateLoader(stringLoader);
        configuration.setDefaultEncoding("UTF-8");

        Template template = configuration.getTemplate("template");
        template.process(model, new OutputStreamWriter(System.out));


     catch (Exception e) 
        // failed validation...
    


上面的字符串应该有效,因为fragment 不为空。但是会抛出以下错误:

2017-11-19 11:11:11.732 错误 4956 --- [-nio-443-exec-8] freemarker.runtime : 执行 FreeMarker 时出错 模板

freemarker.core.InvalidReferenceException:以下已评估 为空或丢失: ==> 片段 [在模板“模板”中第 1 行第 7 列]

---- 提示:如果已知失败的表达式合法地引用了有时为 null 或缺失的内容,请指定默认值 像 myOptionalVar!myDefault 这样的值,或使用 when-presentwhen-missing。 (这些只有 覆盖表达式的最后一步;覆盖整个表达式,

使用括号:(myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??

---- FTL 堆栈跟踪(“~”表示嵌套相关): - 失败于:$fragment.title [在第 1 行第 5 列的模板“模板”中] ---- 在 freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134) ~[freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.UnexpectedTypeException.newDescriptionBuilder(UnexpectedTypeException.java:80) ~[freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.UnexpectedTypeException.(UnexpectedTypeException.java:43) ~[freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.NonHashException.(NonHashException.java:49) ~[freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.Dot._eval(Dot.java:48) ~[freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.Expression.eval(Expression.java:81) ~[freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:96) ~[freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.DollarVariable.accept(DollarVariable.java:59) ~[freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.Environment.visit(Environment.java:327) [freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.Environment.visit(Environment.java:333) [freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.core.Environment.process(Environment.java:306) [freemarker-2.3.25-incubating.jar:2.3.25] 在 freemarker.template.Template.process(Template.java:386) [freemarker-2.3.25-incubating.jar:2.3.25]

我的设置中缺少什么导致 Freemarker 无法“看到”fragment

【问题讨论】:

【参考方案1】:

获取Template 对象本身就足以进行语法验证。根据应用程序,验证模板是否会在运行时失败可能相当棘手,因为您需要一个类似于真实事物的数据模型。

但是让我们假设您可以在您的情况下提供这样的数据模型。那么问题是ModelAndView 不是你的模型。顾名思义,这是您的模型和视图。它只包含你的模型,在里面。 (FreeMarker 不依赖于 Spring,因此只需将该对象用作通用 JavaBean,因此您的变量将是 ModeAndView 对象本身的 JavaBean 属性。)尝试将 ModelAndView.getModel() 传递给 Template.process。 (我不能 100% 确定这是否总是显示所有模型变量,但我猜是这样。无论如何,它扩展了 FreeMarker 识别的 java.util.Map,并将使用 Map.get(varName) 来解析变量。)

【讨论】:

以上是关于如何处理 Freemarker 字符串模板?的主要内容,如果未能解决你的问题,请参考以下文章

自然模板(例如Thymeleaf)时如何处理代码重复?

Freemarker 'Collection.contains' 功能

如何处理模棱两可的模板参数?

如何处理 Meteor 模板中的 switch case

FreeMarker内建函数

如何处理 C++ 内联 + 模板上下文中的警告?