2009年4月13日星期一

FreeMarker中文手册--KLW 模版初览


最简单的模版就是纯HTML文件(或者其他任何文本文件,FreeMarker并不局限于HTML)。当客户端访问这个页面时,FreeMarker会发送这个html到客户端。当然你希望页面是更加动态时,你把FreeMarker能理解的部分加入到HTML中:
  • ${...}:FreeMarker在输出中会用实际值替换大括号中的表达式。这些叫interpolation内插值。见第一个例子
  • FTL 标签(FreeMarker 模版语言标签):FTL标签和HTML标签类似,但是这些标签只是FreeMarker的指令,不会在结果中输出。这些标签都由“#”开始(用户自定的FTL标签由“@”开始,而不是”#”,但是这些是高级主题,见后续翻译)。
  • 注释:模版注释和html注释类似,但是是由<#-- 和 -->标记。这两个界定符之间的任何东西包括界定符本身都会被FreeMarker忽略,不会在结果中输出。

除内插值、FTL标签和注释之外的任何值,都被认定为静态文本,不会被FreeMarker翻译,按原样输出。

FTL标签涉及到所谓的指令。这里的关系如同HTML标签(例如:和<table></table>)和HTML元素(如table元素)之间的关系。(如果你没有感觉到这里的不同,尽管将FTL标签和指令当做同义词吧,没有关系)

指令举例

尽管FreeMarker包含很多指令,但是在这个初步预览里,我们只举三个最常用的指令作为例子。

if 指令

使用if指令,我们可以根据条件跳过模版的某一部分。例如在第一个例子当中,我们想向你的老板Big Joe打招呼,而不是其它用户:

<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>
Welcome ${user}<#if user == "Big Joe">, our beloved leader</#if>!
</h1>
<p>Our latest product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>

这里你告诉FreeMarker,字符串", our beloved leader"仅当变量user的值为"Big Joe"时才会被输出。总的来说,<#if condition>和</#if>之间的内容会被跳过,如果condition值为假的话。

让我们详细地看一下这里的条件:user == "Big Joe"。==是测试左右两边是否相等的操作符,运算结果是一个布尔值,true或者false。在==的左边,我们引用了一个变量,比较时会使用实际值代替。总的来说,在指令或者内插值当中没有引号标记的词FreeMarker都会当做变量来使用。在==的右边,我使用了一个字符串,字符串在模版中必须用引号标记。

如下: 如果price为0的话,会打印"Pythons are free today!":

<#if animals.python.price == 0>
Pythons are free today!
</#if>

类似于刚才直接使用字符串,这里的数字也可以直接使用,注意数字不需要加引号,如果你使用”0”,FreeMarker会将它理解为字符串.

如下: 如果price非0的话,会打印"Python are not free today!".

<#if animals.python.price != 0>
Pythons are not free today!
</#if>

你也可以这样写(使用数据模型初览中的例子):

<#if animals.python.price < animals.elephant.price>
Pythons are cheaper than elephants today.
</#if>

使用<#else>标签,我们指定当condition为假时该做什么.例如:

<#if animals.python.price < animals.elephant.price>
Pythons are cheaper than elephants today.
<#else>
Pythons are not cheaper than elephants today.
</#if>

这个会打印”Pythons are cheaper than elephants today.” 如果python的价格小于elephant的价格,反之则打印”Pythons are not cheaper than elephants today.”

如果你有个包含布尔值的变量(true或者false),你可以直接根在if指令后使用:

<#if animals.python.protected>
Warning! Pythons are protected animals!
</#if>

list 指令

当你想罗列某样东西的时候,list指令变的非常有用.例如,将之前演示序列(数组)的数据模型合并在一个模版中.

<p>We have these animals:
<table border=1>
<tr><th>Name<th>Price
<#list animals as being>
<tr><td>${being.name}<td>${being.price} Euros
</#list>
</table>

输出会是:

<p>We have these animals:
<table border=1>
<tr><th>Name<th>Price
<tr><td>mouse<td>50 Euros
<tr><td>elephant<td>5000 Euros
<tr><td>python<td>4999 Euros
</table>

List指令的通用格式是:

<#list sequence as loopVariable>repeatThis</#list>

repeatThis部分对给定序列的每一项都会重复一次,从第一项开始,一个接着一个.在所有的循环中,loopVariable指向循环的当前值.这个值只存在于<#list …>和<#/list>标签之间(作用域在这两者之间,之外则不可见).

作为另一个例子,我们列出数据模型例子中的所有fruit:

<p>And BTW we have these fruits:
<ul>
<#list whatnot.fruits as fruit>
<li>${fruit}
</#list>
<ul>

你应该熟悉whatnot.fruits这种表达式,见之前数据模型的例子.

include 指令

使用include指令你可以将另一个文件内容插入到模版当中.

假设你要在多个页面下显示版权信息.你可以创建一个仅包含版权信息的文件,然后将该文件插入到任何你需要的地方.如,你将版权信息保存在文件copyright_footer.html中:

<hr>
<i>
Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>,
<br>
All Rights Reserved.
</i>

任何时候,你需要这个文件时,仅简单使用include指令即可:

<html>
<head>
<title>Test page</title>
</head>
<body>
<h1>Test page</h1>
<p>Blah blah...
<#include "/copyright_footer.html">
</body>
</html>

输出会是:

<html>
<head>
<title>Test page</title>
</head>
<body>
<h1>Test page</h1>
<p>Blah blah...
<hr>
<i>
Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>,
<br>
All Rights Reserved.
</i>
</body>
</html>

如果你更新了copyright_footer.html,访问者会在所有页面看到新的版权信息.

使用多个指令

你可以在页面中任意多次地使用指令,并且你可以切套地使用指令,正如你可以在HTML标签中切套地使用其他HTML标签.例如下例会列出所有的animal,并使用粗体打印他们的名字:

<p>We have these animals:
<table border=1>
<tr><th>Name<th>Price
<#list animals as being>
<tr>
<td>
<#if being.size == "large"><font size="+1"></#if>
${being.name}
<#if being.size == "large"></font></#if>
<td>${being.price} Euros
</#list>
</table>

注意这里,因为FreeMarker不对FTL标签,内插值和注释之外的文本翻译,它不会看到上面内嵌的font标签.

处理缺失变量

在实践中,数据模型经常有一些可选的变量(例如,有时候就是未定义).为防止典型的人为错误,FreeMarker不容忍对缺失变量的引用,除非你明确指明如果变量缺失时该做何处理.这里我们会展示两种最典型的处理方法.

给编程人员的提示:一个不存在(未定义)的变量和一个变量但是包含null值,对FreeMarker来说是一样的.所以这里”缺失”一词包含了这两种情况.

无论何时,我们引用一个变量时,我们都可以指定一个默认值,当这个变量缺失时,使用的时候在变量后跟”!”和默认值.如下例中,当user在数据模型中缺失时,模版会使用字符串”Anonymous”代替user.(当user在数据模型中有定义且不为null时,模版会只用准确的值,而”Anonymous”好像不曾在那里一样):

<h1>Welcome ${user!"Anonymous"}!</h1>

你可以在变量名后跟两个问号??来检测变量是否缺失.结合已介绍的if指令你可以跳过整个问候如果user变量缺失的话:

<#if user??><h1>Welcome ${user}!</h1></#if>

对于多步访问的变量,如animals.python.price,animals.python.price!0仅当animals.python都不缺失并且只有最后一个子变量price,可能缺失(在这种情况下值为0)的时候才是正确的.如果animals或者python缺失,模版处理过程会因”未定义变量”错误而停止.为防止出现这种情况,你需要这样写(animals.python.price)!0,加了括号之后,在这种情况下,表达式的值会为0,如果animals或者python缺失的话.同样的逻辑对??(测试运算符)也成立: animals.python.price??和(animals.python.price)??的情况和上面说的一样.

没有评论: