假如我们在模版中引用了一个不存在的变量,FreeMaker将抛出错误信息,如下:
<html> <head> <title>处理不存在的变量</title> </head> <body> <p> version=${version} </p> </body> </html>
上面模版中的 version 变量实际上是不存在。错误信息:
六月 25, 2020 10:34:08 下午 freemarker.log._JULLoggerFactory$JULLogger error 严重: Error executing FreeMarker template FreeMarker template error: The following has evaluated to null or missing: ==> version [in template "template11.ftl" at line 8, column 15] ---- 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</#if>. (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: ${version} [in template "template11.ftl" at line 8, column 13] ----
在数据模型中经常会有可选的变量(也就是说有时并不存在)。除了一些典型的人为原因导致失误外,FreeMarker 绝不能容忍引用不存在的变量,除非明确地告诉它当变量不存在时如何处理。一个不存在的变量和一个是 null 值的变量,对于 FreeMarker 来说是一样的,所以这里所指的 "丢失" 包含这两种情况。下面介绍两种处理变量不存在的方法:
不论在哪里引用变量,都可以指定一个默认值来避免变量丢失这种情况,通过在变量名后面跟着一个 !(叹号) 和 默认值。 例如:
<p> version=${version!"v1.0.0"} </p>
上面当 version 变量不存在时,将输出“v1.0.0”字符串。
也可以使用“?default('默认值')”方式,如下:
<p> version=${version?default("v1.0.0")} </p>
我们还可以在变量名后面通过放置 ?? 来询问一个变量是否存在。将 ?? 和 if 指令合并,如下:
<#if version??> <p> version=${version} </p> </#if>
关于多级访问的变量,比如 user.url.port,书写代码:user.url.port!80 当且仅当 user.url永远存在,而仅仅最后一个子变量 port 可能不存在时是正确的 (这种情况下我们假设默认端口为 80)。如果 user 或 url 不存在, 那么模板处理过程将会以“未定义的变量”错误而停止。如下:
// 数据模型 Map<String, Object> input = new HashMap<String, Object>(); Map<String, Object> user = new HashMap<String, Object>(); user.put("name", "hxstrive"); user.put("email", "hxstrive@outlook.com"); user.put("url", null); // { host:'www.hxstrive.com', protocol:'http', port:80 } input.put("user", user);
模型代码:
<html> <head> <title>处理不存在的变量</title> </head> <body> <p>name:${user.name}</p> <p>email:${user.email}</p> <p>url:${user.url.protocol}://${user.url.host}:${user.url.port}</p> </body> </html>
为了防止这种情况的发生, 可以如下这样来编写代码 (user.url.port)!80。 这种情况就是说 user 或 url 不存在时,表达式的结果是 80。对于 ?? 也是同样用来的处理这种逻辑的; 将 user.url.port?? 改为(user.url.port)??。如下:
<html> <head> <title>处理不存在的变量</title> </head> <body> <p>name:${user.name}</p> <p>email:${user.email}</p> <p>url:${(user.url.protocol)!"http"}://${(user.url.host)!"www.hxstrive.com"}:<#if (user.url.port)??>${user.url.port}</#if></p> </body> </html>