直接指定值

通常我们喜欢是使用直接确定的值而不是计算的结果。直接指定值有下面类型:字符串、数字、布尔值、序列、值域和哈希表

字符串

在文本中确定字符串值的方法是看双引号,比如:"some text",或单引号,比如:'some text',这两种形式是等同的。如果文本自身包含用于字符引用的引号 (" 或 ') 或反斜杠时,应该在它们的前面再加一个反斜杠(\)。这就是转义,转义允许直接在文本中输入任何字符,也包括换行。例如:

${"It's \"quoted\" and
this is a backslash: \\"}

${'It\'s "quoted" and
this is a backslash: \\'}

将会输出:

It's "quoted" and
this is a backslash: \

It's "quoted" and
this is a backslash: \

注意:这里当然可以直接在模板中输入文本而不需要 ${...}。 但是我们在这里用它只是为了示例来说明表达式的使用。

下面的表格是 FreeMarker 支持的所有转义字符。 在字符串使用反斜杠的其他所有情况都是错误的,运行这样的模板都会失败。

转义序列含义
\"引号 (u0022)
\'单引号(又称为撇号) (u0027)
\{起始花括号:{
\\反斜杠 (u005C)
\n换行符 (u000A)
\r回车 (u000D)
\t水平制表符(又称为tab) (u0009)
\b退格 (u0008)
\f换页 (u000C)
\l小于号:<
\g大于号:>
\a&符:&
\xCode字符的16进制&nbspUnicode 码 (UCS 码)

在 \x 之后的 Code 是1-4位的16进制码。下面这个示例中都是在字符串中放置版权符号: "\xA9 1999-2001", "\x0A9 1999-2001", "\x00A9 1999-2001"。 

如果紧跟16进制码后一位的字符也能解释成 16 进制码时,就必须把 4 位补全,否则 FreeMarker 就会误解你的意图。

注意:字符序列 ${ (和 #{) 有特殊的含义,它们被用做插入表达式的数值 (典型的应用是变量的值: "Hello ${user}!")。这将在后续章节中解释。如果想要打印 ${ 或 #{, 就要使用下面所说的原生字符串,或者进行转义。就像 "foo $\{bar}"中的 {。

原生字符串是一种特殊的字符串。在原生字符串中,反斜杠和 ${ 没有特殊含义,它们被视为普通的字符。为了表明字符串是原生字符串,在开始的引号或单引号之前放置字母r,例如:

${r"${foo}"}
${r"C:\foo\bar"}

将会输出:

${foo}
C:\foo\bar

数字

输入不带引号的数字就可以直接指定一个数字,必须使用点作为小数的分隔符而不能是其他的分组分隔符。可以使用 - 或 + 来表明符号正负 (+ 是多余的)。科学记数法暂不支持使用 (1E3 就是错误的),而且也不能在小数点之前不写 0(.5 也是错误的)。

下面的数字都是合法的:0.08, -5.013,8, 008,11, +11

注意:像 08、+8、8.00 和 8 这样的数值是完全等同的,它们都是数字8。所以,${08}、${+8}、${8.00} 和 ${8} 的输出都是一样的。

布尔值

直接写 true 或者 false 就表示一个布尔值了,不需使用引号。

序列

指定一个文字的序列,使用逗号来分隔其中的每个子变量, 然后把整个列表放到方括号中。例如:

<#list ["foo", "bar", "baz"] as x>
${x}
</#list>

将会输出:

foo
bar
baz

列表中的项目是表达式,那么也可以这样做: [2 + 2, [1, 2, 3, 4], "foo"]。其中第一个子变量是数字4,第二个子变量是一个序列, 第三个子变量是字符串"foo"。

值域

值域也是序列,但它们由指定包含的数字范围所创建,而不需指定序列中每一项。比如:0..<m,这里假定 m 变量的值是5,那么这个序列就包含 [0, 1, 2, 3, 4]。值域的主要作用有:使用 <#list...> 来迭代一定范围内的数字,序列切分和字符串切分。

值域表达式的通用形式是 ( start 和 end 可以是任意的结果为数字表达式):

  • start..end:包含结尾的值域。比如 1..4 就是 [1, 2, 3, 4],而 4..1 就是 [4, 3, 2, 1]。当心一点,包含结尾的值域不会是一个空序列,所以 0..length-1 就是错误的,因为当长度是 0 时,序列就成了 [0, -1]。

  • start..<end 或 start..!end:不包含结尾的值域。比如 1..<4 就是 [1, 2, 3],4..<1 就是 [4, 3, 2], 而 1..<1 表示 []。请注意最后一个示例;结果可以是空序列,和 ..< 和 ..! 没有区别; 最后这种形式在应用程序中使用了 < 字符而引发问题 (如HTML编辑器等)。

  • start..*length:限定长度的值域,比如 10..*4 就是 [10, 11, 12, 13],10..*-4 就是 [10, 9, 8, 7],而 10..*0 表示 []。当这些值域被用来切分时,如果切分后的序列或者字符串结尾在指定值域长度之前,则切分不会有问题;注意:限定长度的值域是在 FreeMarker 2.3.21版本中引入的。

  • start..:无右边界值域。这和限制长度的值域很像,只是长度是无限的。比如 1.. 就是 [1, 2, 3, 4, 5, 6, ...],直到无穷大。但是处理 (比如列表显示) 这种值域时要万分小心,处理所有项时,会花费很长时间,直到内存溢出应用程序崩溃。和限定长度的值域一样,当它们被切分时,遇到切分后的序列或字符串结尾时,切分就结束了。

    注意:无右边界值域在 FreeMarker 2.3.21 版本以前只能用于切分,若用于其它用途,它就像空序列一样了。要使用新的特性,使用 FreeMarker 2.3.21 版本是不够的,程序员要设置 incompatible_improvements 至少到2.3.21版本。

值域的进一步注意事项:

  • 值域表达式本身并没有方括号,比如这样编写代码 <#assign myRange = 0..<x>,而不是 <#assign myRange = [0..<x]>。后者会创建一个包含值域的序列。方括号是切分语法的一部分,就像 seq[myRange]。

  • 可以在 .. 的两侧编写算术表达式而不需要圆括号,就像 n + 1 ..< m / 2 - 1。

  • ..,..<, ..! 和 ..* 是运算符,所以它们中间不能有空格。就像 n .. <m 这样是错误的,但是 n ..< m 这样就可以。

  • 无右边界值域的定义大小是2147483647 (如果 incompatible_improvements 低于2.3.21版本,那么就是0), 这是由于技术上的限制(32位)。但当列表显示它们的时候,实际的长度是无穷大。

  • 值域并不存储它们包含的数字,那么对于 0..1 和 0..100000000 来说,创建速度都是一样的, 并且占用的内存也是一样的。

哈希表

在模板中指定一个哈希表,就可以遍历用逗号分隔开的"键/值"对,把列表放到花括号内即可。键和值成对出现并以冒号分隔。比如: { "name": "green mouse", "price": 150 }。 请注意名和值都是表达式,但是用来检索的名称就必须是字符串类型, 而值可以是任意类型。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号