freemarker之模板开发(模板之插值)
----------
插值的使用语法是:${expression},expression可以是所有种类的表达式(比如:${100+x}).
插值是用来给插入具体值然后转换为文本(字符串)。插值仅仅可以在两种位置使有:文本区和字符串表达式中。插值表达式的结果必须是字符串,数字或日期类型的,因为只有数字和日期类型可以自动转换为字符串类型,其他类型的值(如:布尔,序列)只能手动转换为字符串类型,否则就会发生错误导致模板执行中止。
字符串插入指南:不要忘了转义!
如果插值在文本区(也就是说,不再字符串表达式中),如果escapse指令起作用了,即将被插入的字符串会被自动转义。如果你要生成HTML,那么强烈建议你利用它来阻止跨站脚本攻击和非格式良好的HTML页面。如例:
<#escape x as x?html>
...
<p>Title: ${book.title}</p>
<p>Description: <#noescape>${book.description}</#noescape></p>
<h2>Comments:</h2>
<#list comments as comment>
<div class="comment">
${comment}
</div>
</#list>
...
</#escape>
这个示例展示了当生成HTML时,你最好将完整的模板放入到escape指令中。那么,如果book.title包含&,它就会在输出中被替换成&而页面还会保持格式良好的HTML。但是有时在数据模型中真的需要HTML,比如我们假设上面的book.description在数据库中的存储是HTML格式的,那么此时你不得不使用noescape来抵消escape的转义,模板就会像这样了:
...
<p>Title:${book.title?html}</p>
<p>Description: ${book.description}</p>
<h2>Comments:</h2>
<#list comments as comment>
<div class="comment">
${comment?html}
</div>
</#list>
...
这和之前示例的效果是一样的,但是这里你可能会忘记一些?html内建函数,就会有安全上的问题了。在之前的示例中,你可能忘记一些noescape,也会造成不良的输出,但是起码是没有安全隐患的。
数字插入指南
如果表达式是数字类型,那么根据数字的默认格式,数值将会转换成字符串。这也许会包含最大小数,数字分组和相似处理的问题。通常程序员应该设置默认的数字格式,而模板设计者不需要处理它(但是可以使用number_format设置来进行,详情参考setting指令部分的文档)。你可以使用内建函数string为一个插值来重写默认数值格式。
警告:
可以看出,插值的打印都是给用户看的,而不是给计算机的。有时候这样并不好,比如你要打印数据库记录的主键,用来作为URL中的一部分或HTML表单的隐藏域来作为提交内容,或者要打印css/javascript的数字。这些值都是给计算机程序去识别的而不是用户,很多程序对数字格式的要求非常严格,它们只能理解一部分简单的美式数字格式。那样的话,可以使用内建函数c(代表计算机)来解决这个问题,如:
<a href="/shop/productdetails?id=${product.id?c}">Details..</a>
日期/时间插入指南
如果表达式的值是时间日期类型,那么日期中的数字将会按照默认格式来转换成文本。通常程序员应该设置默认格式,而页面设计者无需处理这一点(如果需要的话,可以参考date_format,time_format和datetime_format的setting指令的设置来完成响应操作)。这里也可以使用内建函数string为单独的插值重写默认格式。
警告:
为了将日期显示成文本,freemarker必须知道日期中的哪一部分在使用,也就是说,如果仅仅日期部分(年,月,日)使用或仅仅时间部分(时,分,秒,毫秒)使用或两部分都用。不幸的是,由于java平台技术的限制,自动探测一些变量是不现实的。这时可以找程序员对数据模型中可能出问题的变量进行处理。
布尔值插入指南
若要使用插值方式来打印布尔值会引起错误,中止模板的执行。例如:${a == 2}就会引起错误,它不会打印"true"或其他内容。然而,我们可以使用内建函数string来将布尔值转换为字符串形式。比如打印变量"married"(假设它是布尔值),那么可以这么来写:
${married?string("yes","no)}
精确的转换规则
表达式的值转换为字符串精确的规则就是下面这些,以这个顺序进行:
1.如果这个值是数字,那么它会按照指定的number_format设置规则来转换为字符串。所以这些转换通常是对用户进行的,而不是对计算机。
2.如果这个值是日期,时间或日期类型的一种,那么它们会按照指定的time_format,date_format和datetime_format设置规则来转换为字符串,这要看日期信息中是只包含时间,日期还是全包括了。如果它不能被深测出来是哪种日期类型(日期,时间或日期时间),不需要转换。
3.如果值本来就是字符串类型的,不需要转换。
4.如果freemarker引擎在传统兼容模式下:
a.如果值是布尔类型,那么就转换成"true",false值将会转换为空串。
b.如果表达式未被定义(null或者变量未定义),那么就转换为空串。
c.否则就会发生错误中止模板执行。
5.否则就会发生错误中止模板执行。