假如我们在模版中引用了一个不存在的变量,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>