我需要更改FreeMarker关于处理模板和数据的行为,以防丢失一些数据。 在缺少的情况下,我需要保持模板不变并继续处理。
实施例: 模板:
...
var1 = ${var1}
var2 = ${var2}
...
数据:
var1 = Hello
处理后我需要结果:
...
var1 = Hello
var2 = ${var2}
...
我的解决方案是:
class MyTemplateExceptionHandler implements TemplateExceptionHandler {
public void handleTemplateException(TemplateException te, Environment env, java.io.Writer out)
throws TemplateException {
try {
//2nd word on 2nd row is name of missing variable :(
String missingVariable = te.getMessageWithoutStackTop().split("\n")[1].split(" ")[1];
out.write("${" + missingVariable + "}");
} catch (IOException e) {
throw new TemplateException("Failed to print error message. Cause: " + e, env);
}
} }
并使用:
...
Configuration cfg = new Configuration();
cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());
...
我的解决方案有效,但我不满意,因为:
1)在handleTemplateException()中获取缺失变量非常糟糕。是否存在更好的方法来获取缺失变量的名称?
2)即使我有自己的TemplateExceptionHandler,FreeMarker也会输出足够的信息。我可以改变吗?
缺少变量的示例输出" environment_name":
22.10.2014 9:01:55 freemarker.log._JDK14LoggerFactory$JDK14Logger error
SEVERE: Error executing FreeMarker template
FreeMarker template error:
The following has evaluated to null or missing:
==> environment_name [in template "Osb-PrepareAndDeploy.ftl" at line 33, column 33]
Tip: If the failing expression is known to be legally null/missing, either specify a default value with myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthessis: (myOptionVar.foo)!myDefault, (myOptionVar.foo)??
The failing instruction (FTL stack trace):
----------
==> ${environment_name} [in template "Osb-PrepareAndDeploy.ftl" at line 33, column 31]
----------
Java stack trace (for programmers):
----------
freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:98)
at freemarker.core.EvalUtil.coerceModelToString(EvalUtil.java:382)
at freemarker.core.Expression.evalAndCoerceToString(Expression.java:115)
at freemarker.core.DollarVariable.accept(DollarVariable.java:76)
at freemarker.core.Environment.visit(Environment.java:265)
at freemarker.core.MixedContent.accept(MixedContent.java:93)
at freemarker.core.Environment.visit(Environment.java:265)
at freemarker.core.Environment.process(Environment.java:243)
at freemarker.template.Template.process(Template.java:277)
at net.homecredit.scm.jenkinsTool.countrySettings.Country.createJobs(Country.java:282)
at net.homecredit.scm.jenkinsTool.Start.main(Start.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
答案 0 :(得分:0)
您无法阻止记录异常。 TemplateExceptionHandler
并不意味着从错误中获取非错误,它只是让您决定在错误发生后做什么。比如,您想要打印错误页面或其他内容。在极端情况下,您可能希望在打印一些错误指示符后继续页面呈现,但这仍然是需要修复的错误。
如果你说出为什么需要这个,也许会有所帮助。也许解决方案不是TemplateExceptionHandler
- s。
从更智能的异常处理开始,首先,在处理程序中,您应该检查异常是否为InvalidReferenceException
,因为我猜您不想与其他人打交道。然后,使用getBlamedExpressionString()
(需要FreeMarker 2.3.21),您可以获得要打印到输出的部分内容。它只是其中的一部分,因为如果${x + 1}
因未定义x
而失败,则只返回"x"
,而不是"x + 1"
。