如何处理 Freemarker 字符串模板?
How to process Freemarker String template?
我正在使用 Spring 使用 Freemarker 启动器启动。
给定以下字符串:
<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 ERROR 4956 --- [-nio-443-exec-8]
freemarker.runtime : Error executing FreeMarker
template
freemarker.core.InvalidReferenceException: The following has evaluated
to null or missing:
==> fragment [in template "template" at line 1, column 7]
---- Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default
value like myOptionalVar!myDefault, or use <#if
myOptionalVar??>when-present<#else>when-missing. (These only
cover the last step of the expression; to cover the whole expression,
use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
---- FTL stack trace ("~" means nesting-related):
- Failed at: ${fragment.title} [in template "template" at line 1, column 5]
---- at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
~[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.UnexpectedTypeException.newDesciptionBuilder(UnexpectedTypeException.java:80)
~[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.UnexpectedTypeException.(UnexpectedTypeException.java:43)
~[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.NonHashException.(NonHashException.java:49)
~[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.Dot._eval(Dot.java:48)
~[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.Expression.eval(Expression.java:81)
~[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:96)
~[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.DollarVariable.accept(DollarVariable.java:59)
~[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.Environment.visit(Environment.java:327)
[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.Environment.visit(Environment.java:333)
[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.core.Environment.process(Environment.java:306)
[freemarker-2.3.25-incubating.jar:2.3.25] at
freemarker.template.Template.process(Template.java:386)
[freemarker-2.3.25-incubating.jar:2.3.25]
我的设置中缺少什么导致 Freemarker 无法 'see' fragment
?
获取Template
对象本身就足以进行语法验证。根据应用程序的不同,验证模板是否会在运行时失败可能会相当棘手,因为您需要一个类似于真实事物的数据模型。
但我们假设您可以在您的案例中提供这样的数据模型。那么问题是 ModelAndView
不是你的模型。顾名思义,它是您的模型和视图。它只包含你的模型,在里面。 (FreeMarker 不依赖于 Spring,因此只需将该对象用作通用 JavaBean,因此您的变量将是 ModeAndView
对象本身的 JavaBean 属性。)尝试传递 ModelAndView.getModel()
改为 Template.process
。 (我不是 100% 确定它是否总是显示所有模型变量,但我猜是这样。无论如何,它扩展了 FreeMarker 识别的 java.util.Map
,并将使用 Map.get(varName)
来解析变量。 )
我正在使用 Spring 使用 Freemarker 启动器启动。
给定以下字符串:
<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 ERROR 4956 --- [-nio-443-exec-8] freemarker.runtime : Error executing FreeMarker template
freemarker.core.InvalidReferenceException: The following has evaluated to null or missing: ==> fragment [in template "template" at line 1, column 7]
---- Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression,
use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
---- FTL stack trace ("~" means nesting-related): - Failed at: ${fragment.title} [in template "template" at line 1, column 5] ---- at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134) ~[freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.UnexpectedTypeException.newDesciptionBuilder(UnexpectedTypeException.java:80) ~[freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.UnexpectedTypeException.(UnexpectedTypeException.java:43) ~[freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.NonHashException.(NonHashException.java:49) ~[freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.Dot._eval(Dot.java:48) ~[freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.Expression.eval(Expression.java:81) ~[freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:96) ~[freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.DollarVariable.accept(DollarVariable.java:59) ~[freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.Environment.visit(Environment.java:327) [freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.Environment.visit(Environment.java:333) [freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.core.Environment.process(Environment.java:306) [freemarker-2.3.25-incubating.jar:2.3.25] at freemarker.template.Template.process(Template.java:386) [freemarker-2.3.25-incubating.jar:2.3.25]
我的设置中缺少什么导致 Freemarker 无法 'see' fragment
?
获取Template
对象本身就足以进行语法验证。根据应用程序的不同,验证模板是否会在运行时失败可能会相当棘手,因为您需要一个类似于真实事物的数据模型。
但我们假设您可以在您的案例中提供这样的数据模型。那么问题是 ModelAndView
不是你的模型。顾名思义,它是您的模型和视图。它只包含你的模型,在里面。 (FreeMarker 不依赖于 Spring,因此只需将该对象用作通用 JavaBean,因此您的变量将是 ModeAndView
对象本身的 JavaBean 属性。)尝试传递 ModelAndView.getModel()
改为 Template.process
。 (我不是 100% 确定它是否总是显示所有模型变量,但我猜是这样。无论如何,它扩展了 FreeMarker 识别的 java.util.Map
,并将使用 Map.get(varName)
来解析变量。 )