变量定义html
<#assign name1="北京" name2="上海" name3="广东"> 输出结果:${name1}、${name2}、${name3} <#assign str="你好"> 输出结果:${str} 输出结果:北京、上海、广东 输出结果:你好
<#assign num = 100 /> 适用类型:定义变量,支持计算和赋值java
<#assign num = 101 /><br/> ${num * 10}<br/> ${num / 10}<br/> ${num + 10}<br/> ${num - 10}<br/> 输出结果: 1,010 10.1 111 91
listnode
<#list strList as item>
${item}
</#list>
map程序员
<select id="selOrderStatus" name="orderStatus" class="form-control" > <option value="-1">所有</option> <#assign selected=''/> <#if orderStatusMap?exists> <#list orderStatusMap?keys as key> <#if (key == status?string)> <#assign selected='selected="selected"'/> <#else> <#assign selected=''/> </#if> <option ${selected} value="${key}">${orderStatusMap[key]}</option> </#list> </#if> </select>
switch正则表达式
<#switch "星期三"> <#case "星期一"> 油焖大虾 <#break> <#case "星期二"> 炸酱面 <#break> <#default> 肯德基 </#switch>
输出结果:肯德基
${var!} 对 null 或者不存在的对象进行取值,能够设置默认值,例:${var!'我是默认值'} 即,有值时显示正常值,无值时显示默认值数据库
${封装对象.属性}对封装对象进行取值,例:${User.name} 若是为空,也能够这么写:${order.orderId!"6666"};${order.getOrderCode()}json
${var?html} 转义HTML内容 ${order.getOrderCode()?html}api
string转数字浏览器
<#assign num="200.99"/> ${num?eval} <#if (num?eval >100)> 55557 </#if> 转换结果:200.99
数字转string安全
<#assign num=200.99/> ${num?string} <#if (num?string = "200.99")> true </#if>
字符串函数:
<#list "aa,bb,cc,dd"?split(",") as str> ${str} </#list> 输出结果:aa bb cc dd <br/> ${"hello world"?index_of("o")} 输出结果:4 <br/> ${"hello world"?last_index_of("l")} 输出结果:9 <br/> -${" gg "?trim}- 删除字符串首尾空格 输出结果:-gg- <br/> ${"GROUP VALUE"?lower_case} 小写 输出结果:group value <br/> ${"group value"?upper_case} 大写 输出结果:GROUP VALUE <br/> ${"group value"?cap_first} 第一个单词的首字母大写 输出结果:Group value <br/> ${"GROUP VALUE"?uncap_first} 第一个单词的首字母小写 输出结果:gROUP VALUE <br/> ${"group value"?capitalize} 全部单词的首字母大写 输出结果:Group Value <br/> ${"group value"?contains("val")?string} 判断字符中是否包含某个子串。返回布尔值 输出结果:true <br/> ${"group value"?starts_with("gro")?string} 判断某个字符串是否由某个子串开头,返回布尔值 输出结果:true <br/> ${"group value"?ends_with("lue")?string} 判断某个字符串是否由某个子串结尾,返回布尔值 输出结果:true <br/> ${"group value"?length} 判断字符中是否包含某个子串。返回布尔值 输出结果:11 <br/> ${"strabttuabg"?replace("ab","--")} 所有替换 输出结果: str--ttu--g <br/> ${"<font color = 'red'>我只是个菜单</font>"} ${order.getOrderCode()?html} 输出结果: <br/> ${"group"?substring(0)} ${"group"?substring(1)} ${"group"?substring(2)} ${"group"?substring(3)} 输出结果:group roup oup up <br/> ${"group"?substring(0,1)} ${"group"?substring(1,3)} ${"group"?substring(2,5)} 输出结果: g ro oup
${"abcde"?left_pad(10,"--")} 若是不足10个字符,以--在左边填充
输出结果:-----abcde
${"abcde"?right_pad(10,"--")} 若是不足10个字符,以--在右边填充
输出结果:abcde-----
数字格式化:
<br/> <br/> <br/> <#assign num=898> ${num?string(",##0.00")} 输出结果:898.00 <br/> <#assign num=0.1> ${num?string(",##0.00")} 输出结果:0.10 <br/> <#assign num=1234136.123> ${num?string(",##0.00")} 输出结果:1,234,136.12 <br/> <#assign num=1234136.775> ${num?string(",##0.00")} 输出结果:1,234,136.78 <br/> <#assign num=1234136.777> ${num?string(",##0.00")} 输出结果:1,234,136.78 <br/>------------------------------- <br/> <br/> <#assign num=898> ${num?string("0.00")} 输出结果:898.00 <br/> <#assign num=0.1> ${num?string("0.00")} 输出结果:0.10 <br/> <#assign num=1234136.123> ${num?string("0.00")} 输出结果:1234136.12 <br/> <#assign num=1234136.775> ${num?string("0.00")} 输出结果:1234136.78 <br/> <#assign num=1234136.777> ${num?string("0.00")} 输出结果:1234136.78 <br/>------------------------------- <br/> <br/> <#assign num=898> ${num?string("#.##")} 输出结果:898 <br/> <#assign num=0.1> ${num?string("#.##")} 输出结果:0.1 <br/> <#assign num=1234136.123> ${num?string("#.##")} 输出结果:1234136.12 <br/> <#assign num=1234136.775> ${num?string("#.##")} 输出结果:1234136.78 <br/> <#assign num=1234136.777> ${num?string("#.##")} 输出结果:1234136.78 <br/>------------------------------- <br/> <br/> ${1.2?string("0")} 输出结果:1 <br/> ${1.8?string("0")} 输出结果:2 <br/> ${1.5?string("0")} 输出结果:2 <br/> ${2.5?string("0")} 输出结果:2 <br/> ${1?string("000.00")} 输出结果:001.00 <br/> ${12.1?string("000.00")} 输出结果:012.10 <br/> ${123.456?string("000.00")} 输出结果:123.456 <br/>------------------------------- <br/> <br/> 舍去小数点后面的 ${1.8?int} ${1.5?int} ${1.4?int} 输出结果:1 1 1 <br/>------------------------------- <br/> <br/> <#assign num=1234136.777> ${num?string.number} 输出结果:1,234,136.777 <br/> ${num?string.currency} 输出结果:¥1,234,136.78 <br/> ${num?string.percent} 输出结果:123,413,678% <br/> <br/> <#setting number_format="currency"> <#assign x=5642.785> ${x} ${x?string} ${x?string.number} ${x?string.currency} ${x?string.percent} 输出结果:¥5,642.78 ¥5,642.78 5,642.785 ¥5,642.78 564,278% <br/>------------------------------- <br/> <br/> <#assign numList = [12,0.236,89,12.032,69.56,45.67,-0.561,-8.057,-89.56,4.69]/> <#list numList as num> ${num} ?round=${num?round} ?floor=${num?floor} ?ceiling=${num?ceiling}<br/> </#list> 输出结果: 12 ?round=12 ?floor=12 ?ceiling=12 0.236 ?round=0 ?floor=0 ?ceiling=1 89 ?round=89 ?floor=89 ?ceiling=89 12.032 ?round=12 ?floor=12 ?ceiling=13 69.56 ?round=70 ?floor=69 ?ceiling=70 45.67 ?round=46 ?floor=45 ?ceiling=46 -0.561 ?round=-1 ?floor=-1 ?ceiling=0 -8.057 ?round=-8 ?floor=-9 ?ceiling=-8 -89.56 ?round=-90 ?floor=-90 ?ceiling=-89 4.69 ?round=5 ?floor=4 ?ceiling=5
日期格式化
LocalDateTime 格式化 ${strDate?date}<br/> ${strDate?date("yyyy-MM-dd")}<br/> 输出结果: 2018-7-10 2018-7-10 <br/> LocalDateTime 格式化 ${(strDate?string)?replace("T"," ")?datetime("yyyy-MM-dd HH:mm:ss")}<br/> ${(strDate?string)?replace("T"," ")?date("yyyy-MM-dd")}<br/> ${(strDate?string)?replace("T"," ")?time("yyyy-MM-dd HH:mm:ss")}<br/> 输出结果: 2018-7-10 14:22:17 2018-7-10 14:22:17 <br/> <br/> 字符串格式化 ${"2012-06-17 01:08:18"?datetime("yyyy-MM-dd HH:mm:ss")}<br/> ${"2012-06-17 01:08:18"?date("yyyy-MM-dd")}<br/> ${"2012-06-17 01:08:18"?time("yyyy-MM-dd HH:mm:ss")}<br/> 输出结果: 2012-6-17 1:08:18 2012-6-17 1:08:18
long newDateLong=new Date().getTime();
<br/>
${newDateLong?number_to_datetime}
输出结果:2018-7-10 14:46:53
<br>
${newDateLong?number_to_date}
输出结果:2018-7-10
<br>
<br/>-------------------------------
<br/>
LocalDateTime localDateTime = LocalDateTime.now();
Objects.requireNonNull(localDateTime, "arg dt");
long localDateTimeLong = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
<br/>
${localDateTimeLong?number_to_datetime}
输出结果:2018-7-10 14:46:53
<br>
${localDateTimeLong?number_to_date}
输出结果:2018-7-10
<br/>
<br/>-------------------------------
<br/>
Objects.requireNonNull(localDate, "arg dt");
long localDateLong = localDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
<br/>
${localDateLong?number_to_datetime}
输出结果:2018-7-10 0:00:00
<br>
${localDateLong?number_to_date}
输出结果:2018-7-10
布尔值
<#assign foo=true> ${foo?string} ${foo?string("yes","no")} 输出结果: true yes
substring
${"group"?substring(0)} ${"group"?substring(1)} ${"group"?substring(2)} ${"group"?substring(3)} 输出结果: group roup oup up ${"group"?substring(0,1)} ${"group"?substring(1,3)} ${"group"?substring(2,5)} 输出结果: g ro oup
lower_case将字符串转为小写
${"STRING"?lower_case}
输出结果:string
upper_case将字符串转为大写
${"string"?upper_case}
输出结果: STRING
cap_first 将字符串中的第一个单词的首字母变为大写。
${"group"?cap_first}
输出结果:Group
uncap_first将字符串中的第一个单词的首字母变为小写。
${"GROUP"?uncap_first}
输出结果:gROUP
capitalize 将字符串中的全部单词的首字母变为大写
${"group value"?capitalize}
输出结果:
Group Value
contains 判断字符中是否包含某个子串。返回布尔值
${"string"?contains("ing")?string} 输出结果:true
ends_with 判断某个字符串是否由某个子串结尾,返回布尔值。
${"string"?ends_with("ing")?string} 输出结果:true
index_of(substring,start)在字符串中查找某个子串,返回找到子串的第一个字符的索引,若是没有找到子串,则返回-1。
Start参数用于指定从字符串的那个索引处开始搜索,start为数字值。
若是start大于字符串长度,则start取值等于字符串长度,若是start小于0, 则start取值为0。
${"string"?index_of("in")} ${"string"?index_of("ab")} 输出结果: 3 -1
length返回字符串的长度
${"string"?length}
输出结果:6
number将字符串转换为数字
${"111.11"?number}
输出结果:111.11
replace 所有替换
${"strabttuabg"?replace("ab","--")}
输出结果: str--ttu--g
split使用指定的分隔符将一个字符串拆分为一组字符串
<#list "aa,bb,cc,dd"?split(",") as str> ${str}<br/> </#list> 输出结果: aa bb cc dd
转载:
Freemarker内建函数 1.1 处理字符串的内建函数 1.1.1 substring 取子串 注意: 这个内建函数从 FreeMarker 2.3.7 开始可用。 概要 :exp?substring(from, toExclusive) ,也 可 以 做 为 exp?substring(from) 调用 一个字符串的子串。 from 是第一个字符开始的索引。它必须是一个数字并且至少是0, 并且要小于或等于 toExclusive ,不然错误就会中断模板的处理。 toExclusive 是 子串中最后一个字符以后的位置索引,换句话说,它比最后一个字符的索引大 1。它必须是 数字,至少是 0,要小于或等于字符串的长度,不然错误就会停止模板的处理。若是 toExclusive 被忽略了,那么它默认就是字符串的长度。若是参数不是整型的数字,那 么数值中只有整型的部分会被使用。 例如: 输出为: - ${'abc'?substring(0)} - ${'abc'?substring(1)} - ${'abc'?substring(2)} - ${'abc'?substring(3)} - ${'abc'?substring(0, 0)} - ${'abc'?substring(0, 1)} - ${'abc'?substring(0, 2)} - ${'abc'?substring(0, 3)} - ${'abc'?substring(0, 1)} - ${'abc'?substring(1, 2)} - ${'abc'?substring(2, 3)} 输出为: - abc - bc - c - - - a - ab - abc - a - b - c 1.1.2 cap_first 首字母大写 字符串中的第一个单词的首字母大写。更精确的“单词”的意思能够查看内建函数 word_list。 好比: ${" green mouse"?cap_first} ${"GreEN mouse"?cap_first} ${"- green mouse"?cap_first} 输出为: 在 "- green mouse" 的情形下,第一个单词是 - 。 1.1.3 uncap_first 首字母小写 这和 cap_first 是相反的。字符串第一个单词的首字母小写。 1.1.4 capitalize 首字母 大写 字符串的全部单词都大写。更精确的“单词”的意思能够查看内建函数 word_list。好比: 输出为: ${" green mouse"?cap_first} ${"GreEN mouse"?cap_first} 输出为: Green mouse GreEN mouse 1.1.5 chop_linebreak 切断换行符 若是在末尾没有换行符的字符串,那么能够换行,不然不改变字符串。 1.1.6 date ,time ,datetime 日期,时间,时间日期 字符串转换成日期值。建议指定一个肯定格式个参数。好比: <#assign test1 ="10/25/1995"?date("MM/dd/yyyy")> <#assign test2 ="15:05:30"?time("HH:mm:ss")> <#assign test3 = "1995-10-25 03:05PM"?datetime("yyyy-MM-dd hh:mm a")> ${test1} ${test2} ${test3} 将会打印出(基于当地(语言)和其余设置决定输出)以下内容: Oct 25, 1995 3:05:30 PM Oct 25, 1995 3:05:00 PM 要注意日期根据 date_format , time_format 和 datetime_format 的设 置转换回字符串(对于日期转换成字符的更多内容请阅读:日期内建函数,日期插值)。这 和你在转换字符串到日期类型时使用什么格式没有关系。 若是你了解模板处理时默认的日期/时间/时间日期格式,你能够不用格式化参数: <#assign test1 = "Oct 25,1995"?date> <#assign test2 = "3:05:30PM"?time> <#assign test3 = "Oct 25, 199503:05:00 PM"?datetime> ${test1} ${test2} ${test3} 若是字符串不在适当的格式,当你尝试使用这些内建函数时,错误将会中断模板执行。 1.1.7 ends_with 以… 结尾 返回是否这个字符串以指定的子串结尾。好比 "redhead"?ends_with("head") 返回布尔值 true。并且 "head"?ends_with("head") 也返回 true。 1.1.8 html HTML 格式的转义文本 字符串按照 HTML 标记输出。也就是说,下面字符串将会被替代: < 用 < 替换; > 用 > 替换; & 用 & 替换; " 用 " 替换; 注意若是你想安全地插入一个属性,你必须在 HTML 模板中使用引号标记(是 " ,而不 是 ' )为属性值加引号: <input type=text name=uservalue="${user?html}"> 注意在 HTML 页面中,一般你想对全部插值使用这个内建函数。因此你可使用 escape 指令来节约不少输入,减小偶然错误的机会。 1.1.9 group 分组 这个函数只和内建函数 matches 的结果使用。请参考 matches 函数。 1.1.10 index_of 索引所在位置 返回第一次字符串中出现子串时的索引位置。例如 "abcabc"?index_of("bc") 将会返回 1(不要忘了第一个字符的索引是 0)。并且,你能够指定开始搜索的索引位置:将 "abcabc"?index_of("bc",2) 会返回 4。这对第二个参数的数值没有限制:若是 它是负数,那就和是 0 是 ige 效果了,若是它比字符串的长度还大,那么就和它是字符串长 度那个数值是一个效果。小数会被切成整数。 若是第一个参数做为子串没有在该字符串中出现时(若是你使用了第二个参数,那么就 从给定的序列开始。),那么就返回-1. 1.1.11 j_string Java 语言规则的字符串转义 根据 Java 语言字符串转义规则来转义字符串,因此它很安全的将值插入到字符串类型 中。要注意它不会 在被插入的值的两侧添加引号;你须要在这里使用字符串值。 全部 UCS 编码下指向 0x20 的字符会被转义。当它们在 Java 语言中(好比 \n , \t 等) 没有专门的转义序列时,将会被用 UNICODE 进行转义替换( \uXXXX )。 例如: <#assign beanName = 'The "foo"bean.'> String BEAN_NAME ="${beanName?j_string}"; 将会打印: String BEAN_NAME = "The\"foo\" bean."; 1.1.12 js_string JavaScript 语言规则的字符串转义 根据 JavaScript 语言字符串转义规则来转义字符串,因此它很安全的将值插入到字符串 类型中。要注意,它不会 在被插入的值两侧添加引号;而是在字符串中间使用。 引号( " )和单引号( ' )要被转义。从 FreeMarker 2.3.1 开始,也要将 > 转义为 \> (为 了避免 </script> )。 全部在 UCS 编码下指向 0x20 的字符将会被转义。当它们在 JavaScript 中没有专用的转 义序列时(好比 \n , \t 等),它们会被 UNICODE 字符代替( \uXXXX )。 例如: <#assign user = "Big Joe's\"right hand\""> <script> alert("Welcome${user?js_string}!"); </script> 将会打印: <script> alert("Welcome Big Joe\'s \"righthand\"!"); </script> 1.1.13 json_string JSON 规则的字符串转义 根据 JSON 语言的字符串规则来转义字符串,因此在字符串中插入值是安全的。要注意 它不会 在被插入的值两侧添加引号;而是在字符串中间使用。 这不会转义 ' 字符,由于 JSON 字符串必须使用 " 来括起来。它会在 < 以后直接出现的 / (斜杠)字符转义为 \/ ,来避免 </script> 等。它也会在]]以后转义 > 字符为 \u003E , 来避免退出 XML 的 CDATA 段。 全部在 UCS 编码下指向0x20 的字符会被转义。当在 JSON 中没有专用的转义序列时(比 如 \n , \t 等),它们会被 UNICODE 字符代替( \uXXXX )。 1.1.14 last_index_of 最后的索引所在位置 返回最后一次(最右边)字符串中出现子串时的索引位置。它返回子串第一个(最左边) 字符所在位置的索引。例如 "abcabc"?last_index_of("ab") :将会返回 3。并且 你能够指定开始搜索的索引。例如: "abcabc"?last_index_of("ab", 2) ,将 会返回 0。要注意第二个参数暗示了子串开始的最大索引。对第二个参数的数值没有限制: 若是它是负数,那么效果和是零的同样,若是它比字符串的长度还大,那么就和它是字符串 长度那个数值是一个效果。小数会被切成整数。 若是第一个参数做为子串没有在该字符串中出现时(若是你使用了第二个参数,那么就 从给定的序列开始。),那么就返回-1. <#assign user = "Big Joe's\"right hand\""> <script> alert("Welcome${user?js_string}!"); </script> <script> alert("Welcome Big Joe\'s \"righthand\"!"); </script> 1.1.15 length 字符串长度 字符串中字符的数量 1.1.16 lower_case 小写形式 字符 串的 小 写形 式 。比 如 "GrEeNMoUsE?lower_case" 将会是 "green mouse" 。 1.1.17 left_pad 距左边 注意: 这个内建函数从 FreeMarker 2.3.1 版本开始可用。在 2.3 版本中是没有的。 若是它仅仅用 1 个参数,那么它将在字符串的开始插入空白,直到整个串的长度达到参 数指定的值。若是字符串的长度达到指定数值或者比指定的长度还长,那么就什么都不作了。 好比这样: 将会打印: 若是使用了两个参数,那么第一个参数表示的含义和你使用一个参数时的相同,第二个 参数指定用什么东西来代替空白字符。好比: [${""?left_pad(5)}] [${"a"?left_pad(5)}] [${"ab"?left_pad(5)}] [${"abc"?left_pad(5)}] [${"abcd"?left_pad(5)}] [${"abcde"?left_pad(5)}] [${"abcdef"?left_pad(5)}] [${"abcdefg"?left_pad(5)}] [${"abcdefgh"?left_pad(5)}] [ ] [ a] [ ab] [ abc] [ abcd] [abcde] [abcdef] [abcdefg] [abcdefgh] 将会打印: 第二个参数也能够是个长度比 1 大的字符串。那么这个字符串会周期性的插入,好比: 将会打印: 第二个参数必须是个字符串值,并且至少有一个字符。 1.1.18 right_pad 距右边 注意: 这个内建函数从 FreeMarker 2.3.1 版本开始可用。在 2.3 版本中是没有的。 这个和 left_pad 相同,可是它从末尾开始插入字符而不是从开头。 好比: [${""?left_pad(5,"-")}] [${"a"?left_pad(5,"-")}] [${"ab"?left_pad(5,"-")}] [${"abc"?left_pad(5,"-")}] [${"abcd"?left_pad(5,"-")}] [${"abcde"?left_pad(5,"-")}] 将会打印: [-----] [----a] [---ab] [--abc] [-abcd] [abcde] 第二个参数也能够是个长度比 1 大的字符串。那么这个字符串会周期性的插入,好比: [${""?left_pad(8,".oO")}] [${"a"?left_pad(8,".oO")}] [${"ab"?left_pad(8,".oO")}] [${"abc"?left_pad(8,".oO")}] [${"abcd"?left_pad(8,".oO")}] 将会打印: [.oO.oO.o] [.oO.oO.a] [.oO.oOab] [.oO.oabc] [.oO.abcd] 第二个参数必须是个字符串值,并且至少有一个字符。 1.1.19 contains 包含 注意: 这个内建函数从 FreeMarker 2.3.1 版本开始可用。在 2.3 版本中是没有的。 若是函数中的参数能够做为源字符串的子串,那么返回 true。 好比: <#if"piceous"?contains("ice")>It contains"ice"</#if> 将会输出: It contains "ice" 1.1.20 matches 匹配 这是一个“超级用户”函数。无论你是否懂正则表达式。 注意: 这个函数仅仅对使用 Java2 平台的 1.4 版本以后起做用。不然它会发生错误并停止模板 的处理。 这个函数决定了字符串是否精确匹配上模式。并且,它返回匹配的子串列表。返回值是 一个多类型的值: 布尔值:若是字符串精确匹配上模式返回true ,不然返回 false 。例如, "fooo"?matches('fo*') 是 true , 但 是 "fooo bar"?matches('fo*') 是 false 。 序列:字符串匹配子串的列表。多是一个长度为 0 的序列。 好比: <#if"fxo"?matches("f.?o")>Matches.<#else>Does not match.</#if> <#assign res = "foo barfyo"?matches("f.?o")> <#if res>Matches.<#else>Doesnot match.</#if> Matching sub-strings: <#list res as m> - ${m} </#list> 将会打印: 若是正则表达式包含分组(括号),那么你可使用内建函数 groups 来访问它们: 这会打印: matches 接受两个可选的标记参数,要注意它不支持标记fr ,并且也会忽略标记 r 。 <#if"fxo"?matches("f.?o")>Matches.<#else>Does not match.</#if> <#assign res = "foo bar fyo"?matches("f.?o")> <#if res>Matches.<#else>Doesnot match.</#if> Matching sub-strings: <#list res as m> - ${m} </#list> Matches. Does not match. Matching sub-strings: - foo - fyo <#assign res = "aa/rx;ab/r;"?matches("(\\w[^/]+)/([^;]+);")> <#list res as m> - ${m} is ${m?groups[1]} per ${m?groups[2]} </#list> - aa/rx; is aa per rx - ab/r; is ab per r matches 接受两个可选的标记参数,要注意它不支持标记fr ,并且也会忽略标记 r 。 1.1.21 number 数字格式 字符串转化为数字格式。这个数字必须是你在 FTL 中直接指定数值的格式。也就是说, 它必须以本地独立的形式出现,小数的分隔符就是一个点。此外这个函数认识科学记数法。 (好比 "1.23E6" , "1.5e-8" )。 若是这恶搞字符串不在恰当的格式,那么在你尝试访问这个函数时,错误会抛出并停止 模板的处理。 已知的问题:若是你使用比 Java2 平台 1.3 版本还早的版本,这个函数将不会被识别, 前缀和科学记数法都不会起做用。 1.1.22 replace 替换 在源字符串中,用另一个字符穿来替换原字符串中出现它的部分。它不处理词的边界。 好比: ${"this is a caracarus"?replace("car", "bulldozer")} 将会打印: this is a bulldozer abulldozerus 替换是从左向右执行的。这就意味着: ${"aaaaa"?replace("aaa","X")} 将会打印: Xaa 若是 第 一 个 参 数 是 空 字 符 串 , 那 么 所 有 的 空 字 符 串 将 会 被 替 换 , 比 如 "foo"?replace("","|"),就会获得 "|f|o|o|" 。 replace 接受一个可选的标记参数,做为第三个参数。 1.1.23 rtf 富文本 字符串做为富文本(RTF 文本),也就是说,下列字符串: \ 替换为 \\ { 替换为 \{ } 替换为 \} 1.1.24 url URL 转义 注意: 这个内建函数从 FreeMarker 2.3.1 版本开始可用。在 2.3 版本中是没有的。 在 URL 以后的字符串进行转义。这意味着,全部非 US-ASCII 的字符和保留的 URL 字符 将会被 %XX 形式来转义。例如: <#assign x = 'a/b c'> ${x?url} 输出将是(假设用来转义的字符集是 US-ASCII 兼容的字符集): a%2Fb%20c 注意它会转义全部保留的 URL 字符( / , = , & 等),因此编码能够被用来对查询参数的 值进行,好比: <ahref="foo.cgi?x=${x?url}&y=${y?url}">Click here...</a> 注意: 上面的没有 HTML 编码( ?htm )是必要的,由于 URL 转义全部保留的 HTML 编码。但 是要当心:一般引用的属性值,用普通引号( " )包括,而不是单引号( ' ),由于单引号是 不被 URL 转义的。 为了进行 URL 转义,必需要选择字符集,它被用来计算被转义的部分( %XX )。若是你 是 HTML 页面设计者,并且你不懂这个,不要担忧:程序员应该配置 FreeMarker,则它默认 使用恰当的字符集(程序员应该多看看下面的内容)。若是你是一个比较热衷于技术的人, 那么你也许想知道被 url_escaping_charset 设置的指定字符集,它能够在模板的 执行时间设置(或者,更好的是,由程序员以前设置好)。例如: <#-- This will use the charset specified by theprogrammers before the template execution has started. --> <ahref="foo.cgi?x=${x?url}">foo</a> <#-- Use UTF-8 charset for URL escapingfrom now: --> <#settingurl_escaping_charset="UTF-8"> <#-- This will surely use UTF-8 charset--> <ahref="bar.cgi?x=${x?url}">bar</a> 此外,你能够明确地指定一个为单独 URL 转义的字符集,做为内建函数的参数: <ahref="foo.cgi?x=${x?url('ISO-8895-2')}">foo</a> 若是内建函数 url 没有参数,那么它会使用由 url_escaping_charset 设置的 字符集。这个设置应该被软件设置,包括 FreeMarker (好比一个 Web 应用框架),由于它不 会被 默 认 设 置 为 null 。 如 果 它 没 有 被 设 置 , 那 么 FreeMarker 退 回 使 用 output_encoding 的设置,这个也会被默认设置,因此它也是又软件设置的。若是 output_encoding 也没有被设置,那么没有参数的内建函数 url 将不会被执行,二 期它会引发运行时错误。固然,有参数的 url 函数将会执行。 用 setting 指令在模板中设置 url_escaping_charset 是可能的。至少在真 实的 MVC 应用中,这是一个很差的实践行为。 output_encoding 不能由 setting 指令来设置,因此它应该是软件的工做。你能够阅读程序开发指南 / 其它 / 字符集问题来获取更多信息。 1.1.25 split 分割 它被用来根据另一个字符串的出现将原字符串分割成字符串序列。好比: <#list"someMOOtestMOOtext"?split("MOO") as x> - ${x} </#list> 将会打印: - some - test - text 既然已经假设全部分隔符的出现是在新项以前,所以: <#list"some,,test,text,"?split(",") as x> - "${x}" </#list> 将会打印: - "some" - "" - "test" - "text" - "" split 函数接受一个可选的标记参数做为第二个参数。 1.1.26 starts_with 以… 开头 若是 字 符 串 以 指 定 的 子 字 符 串 开 头 , 那 么 返 回 true 。 比 如 "redhead"?starts_with("red")返 回 布 尔 值 true , 而 且 "red"?starts_with("red")也返回 true。 1.1.27 string (当被用做是字符串值时) 什么也不作,仅仅返回和其内容一致的字符串。例外的是,若是值是一个多类型的值(比 如同时有字符串和序列两种),那么结果就只是一个简单的字符串,而不是多类型的值。这 能够被用来防止多种人为输入。 1.1.28 trim 修整字符串 去掉字符串首尾的空格。例如: 输出是: 1.1.29 upper_case 大写形式 字符串的大写形式。好比 "GrEeN MoUsE" 将会是 "GREENMOUSE" 。 1.1.30 word_list 词列表 包含字符串词的列表,并按它们在字符串中的顺序出现。词是连续的字符序列,包含任 意字符,可是不包括空格。好比: <#assign words = " a bcd, .1-2-3"?word_list> <#list words asword>[${word}]</#list> 将会输出: [a][bcd,][.][1-2-3] 1.1.31 xhtml XHTML 格式 字符串做为 XHTML 格式文本输出,下面这些: < 替换为 < > 替换为 > & 替换为 & " 替换为 " ' 替换为 ' 这个函数和 xml 函数的惟一不一样是 xhtml 函数转义 ' 为 ' ,而不是 ' , 可是一些老版本的浏览器不正确解释 ' 。 1.1.32 xml XML 格式 字符串做为 XML 格式文本输出,下面这些: < 替换为 < > 替换为 > (${" green mouse "?trim}) (green mouse) <#assign words = " a bcd, .1-2-3"?word_list> <#list words asword>[${word}]</#list> [a][bcd,][.][1-2-3] & 替换为 & " 替换为 " ' 替换为 ' 1.1.33 通用标记 不少字符串函数接受一个可选的被称为“标记”的字符串参数。在这些字符串中,每一 个字符都影响着内建函数行为的一个特定方面。好比,字母 i 表示内建函数不该该在同一 个字母的大小写上有差别。标记中字母的顺序并不重要。 下面是标记字母的完整列表: i :大小写不敏感:不区分同一个字母大小写之间的差别。 f :仅仅是第一。也就是说,替换/查找等,只是第一次出现的东西。 r :查 找的 子串 是正 则表 达式 。FreeMarker 使用 变化 的正 则表 达式 ,在 http://java.sun.com/j2se/1.4.1/docs/api/java/util/regex/Pattern.html中描述。 只有 你使用 Java2 平台的 1.4 版本之后,标记才会起做用。不然它会发生错误致使模板 处理中止。 m :正则表达式多行模式。在多行模式下,表达式^ 和 $ 仅仅匹配先后,分别是一 行结尾或者是字符串的结束。默认这些表达式仅仅匹配整个字符串的开头和结尾。 注意 ^ 和 $ 不会匹配换行符自己。 s :启用正则表达式的 do-tall 模式(和 Perl 的单行模式同样)。在do-tall 模式下, 表达式 . 匹配任意字符串,包括行结束符。默认这个表达式不匹配行结束符。 c :在正则表达式中许可空白和注释。 示例: <#assign s = 'foo bAr baar'> ${s?replace('ba', 'XY')} i: ${s?replace('ba', 'XY', 'i')} if: ${s?replace('ba', 'XY', 'if')} r: ${s?replace('ba*', 'XY', 'r')} ri: ${s?replace('ba*', 'XY', 'ri')} rif: ${s?replace('ba*', 'XY', 'rif')} 这会输出: foo bAr XYar i: foo XYr XYar if: foo XYr baar r: foo XYAr XYr ri: foo XYr XYr rif: foo XYr baar 这是内建函数使用通用标记的表格,哪些支持什么样的标记。 内建函数 i (忽略大小写) r (正则表达式) m (多行模式) s(dot-all模式) c (whitesp和注释) f (仅第一个) replace 是 是 只和 r 只和 r 只和 r 是 split 是 是 只和 r 只和 r 只和 r 否 match 是 忽略 是 是 是 否 1.2 处理数字的内建函数 相关的 FAQs:若是你有和 1,000,000 或 1 000 000 而不是 1000000 相似的东西,或者是 3.14 而不是 3,14 的东西,反之亦然,请参考FAQ 中相关内容,也要注意内建函数 c 的全部 内容。 1.2.1 c 数字转字符 注意: 这个内建函数从 FreeMarker 2.3.3 之后开始存在。 这个函数将数字转换成字符串,这都是对计算机来讲的,而不是对用户。也就是说,它 根据程序语言的用法来进行格式化,这对于 FreeMarker 的全部本地数字格式化设置来讲是 独立的。它一般使用点来做为小数分隔符,并且它历来不用分组分隔符(像 3,000,000),指 数形式(好比 5E20),多余的在开头或结尾的 0(好比 03 或 1.0),还有+号(好比+1)。它最 多在小数点后打印 16 位,所以数值的绝对值小于 1E-16 将会显示为 0。这个函数很是严格, 由于做为默认(像 ${x} 这样)数字被本地(语言,国家)特定的数字格式转换为字符串, 这是让用户来看的(好比 3000000 可能会被打印为 3,000,000)。当数字不对用户打印时(比 如,对于一个数据库记录 ID,用做是 URL 的一部分,或者是 HTML 表单中的隐藏域,或者 打印 CSS/JavaScript 的数值文本),这个函数必须被用来打印数字(也就是使用 ${x?c} 来代 替 ${x} ),不然输出可能因为当前数字格式设置,本地化(好比在一些国家中,小数点不 是点,而是逗号)和数值(像大数可能被分组分隔符“损坏”)而损坏。 1.2.2 string (当用做是数值类型时) 数字转字符串 将一个数字转换成字符串。它使用程序员已经指定的默认格式。你也能够明确地用这个 函数再指定一个数字格式,这在后面会展现。 有四种预约义的数字格式: computer , currency , number 和 percent 。这 些格式的明确含义是本地化(国家)指定的,受Java 平台安装环境所控制,而不是 FreeMarker, 除了 computer ,用做和函数 c 是相同的格式。你能够这样来使用预约义的格式: <#assign x=42> ${x} ${x?string} <#-- the same as ${x} --> ${x?string.number} ${x?string.currency} ${x?string.percent} ${x?string.computer} 若是你本地是 US English,那么就会生成: 42 42 42 $42.00 4,200% 42 前三个表达式的输出是相同的,由于前两个表达式是默认格式,这里是数字。你可使 用一个设置来改变默认设置: <#settingnumber_format="currency"> <#assign x=42> ${x} ${x?string} <#-- the same as ${x} --> ${x?string.number} ${x?string.currency} ${x?string.percent} 如今会输出: $42.00 $42.00 42 $42.00 4,200% 由于默认的数字格式被设置成了“货币”。 除了这三种预约义格式,你可使用 Java 中数字格式语法写的任意的数字格式 (http://java.sun.com/j2se/1.4/docs/api/java/text/DecimalFormat.html): <#assign x = 1.234> ${x?string("0")} ${x?string("0.#")} ${x?string("0.##")} ${x?string("0.###")} ${x?string("0.####")} ${1?string("000.00")} ${12.1?string("000.00")} ${123.456?string("000.00")} ${1.2?string("0")} ${1.8?string("0")} ${1.5?string("0")} <-- 1.5,rounded towards even neighbor ${2.5?string("0")} <-- 2.5,rounded towards even neighbor ${12345?string("0.##E0")} 输出这些: 1 1.2 1.23 1.234 1.234 001.00 012.10 123.46 1 2 2 <-- 1.5, rounded towards even neighbor 2 <-- 2.5, rounded towards even neighbor 1.23E4 在金融和统计学中,四舍五入都是根据所谓的一半原则,这就意味着对最近的“邻居” 进行四舍五入,除非离两个邻居距离相等,这种状况下,它四舍五入到偶数的邻居。若是你 注意看 1.5 和 2.5 的四舍五入的话,这在上面的示例中是能够看到的,两个都被四舍五入到 2,由于 2 是偶数,但 1 和 3 是奇数。 除了 Java 小数 语 法 模 式 之 外 , 你 可 以 编 写 如 ${aNumber?string("currency")} 这 样 的 代 码 , 它 会 作 和 ${aNumber?string.currency} 同样的事情。 正如以前展现的预约义格式,默认的数字格式也能够在模板中进行设置: <#settingnumber_format="0.##"> ${1.234} 输出这个: 1.23 要注意数字格式是本地化敏感的: <#setting locale="en_US"> US people write:${12345678?string(",##0.00")} <#setting locale="hu"> Hungarian people write:${12345678?string(",##0.00")} 输出这个: US people write: 12,345,678.00 Hungarian people write: 12 345 678,00 1.2.3 round,floor,ceiling 数字的舍入 处理 注意: 内建函数 round 从 FreeMarker 2.3.13 版本以后才存在。 使用肯定的舍入法则,转换一个数字到整数: round :返回最近的整数。若是数字以.5 结尾,那么它将进位(也就是说向正无 穷方向进位) floor :返回数字的舍掉小数后的整数(也就是说向服务穷舍弃) ceiling :返回数字小数进位后的整数(也就是说向正无穷进位) 示例: <#assign testlist=[ 0, 1, -1, 0.5, 1.5, -0.5, -1.5, 0.25, -0.25, 1.75, -1.75]> <#list testlist as result> ${result} ?floor=${result?floor} ?ceiling=${result?ceiling} ?round=${result?round} </#list> 打印: 0 ?floor=0 ?ceiling=0 ?round=0 1 ?floor=1 ?ceiling=1 ?round=1 -1 ?floor=-1 ?ceiling=-1 ?round=-1 0.5 ?floor=0 ?ceiling=1 ?round=1 1.5 ?floor=1 ?ceiling=2 ?round=2 -0.5 ?floor=-1 ?ceiling=0 ?round=0 -1.5 ?floor=-2 ?ceiling=-1 ?round=-1 0.25 ?floor=0 ?ceiling=1 ?round=0 -0.25 ?floor=-1 ?ceiling=0 ?round=0 1.75 ?floor=1 ?ceiling=2 ?round=2 -1.75 ?floor=-2 ?ceiling=-1 ?round=-2 这些内建函数在分页处理时也许有用。若是你仅仅想展现数字的舍入形式,那么你应该 使用内建函数 string 和 numer_format 设置。 1.3 处理日期的内建函数 1.3.1 string (当用做日期值时)日期转字符串 这个内建函数以指定的格式转换日期类型到字符串类型。(当默认格式由 FreeMarker 的 date_format , time_format 和datetime_format 设置来支配时是很好的选 择,那么你就不须要使用这个内建函数了。) 格式能够是预约义格式中的一种,或者你能够指定明确的格式化模式。 预约义的格式是 short , medium , long 和 full ,它们定义了冗长的结果文本输 出。例如,若是输出的本地化是 U.S. English,并且时区是 U.S. Pacific,那么下面的代码: ${openingTime?string.short} ${openingTime?string.medium} ${openingTime?string.long} ${openingTime?string.full} ${nextDiscountDay?string.short} ${nextDiscountDay?string.medium} ${nextDiscountDay?string.long} ${nextDiscountDay?string.full} ${lastUpdated?string.short} ${lastUpdated?string.medium} ${lastUpdated?string.long} ${lastUpdated?string.full} 将会打印这样的内容: 12:45 PM 12:45:09 PM 12:45:09 PM CEST 12:45:09 PM CEST 4/20/07 Apr 20, 2007 April 20, 2007 Friday, April 20, 2007 4/20/07 12:45 PM Apr 20, 2007 12:45:09 PM April 20, 2007 12:45:09 PM CEST Friday, April 20, 2007 12:45:09 PM CEST short , medium , long 和 full 的精确含义是以当前本地(语言)设置为主的。 此外,它不是由 FreeMarker 肯定的,而是由你运行 FreeMarker 的 Java 平台实现的。 对于包含日期和时间两部分的日期类型,你能够分别指定日期和时间部分的长度: ${lastUpdated?string.short_long} <#--short date, long time --> ${lastUpdated?string.medium_short} <#--medium date, short time --> 将会输出: 4/8/03 9:24:44 PM PDT Apr 8, 2003 9:24 PM 注意 ?string.short 和 ?string.short_short 是相 同 的, ?string.medium 和 ?string.medium_medium 是相同的,等等。 警告! 不幸的是,因为 Java 平台的限制,你能够在数据模型中保存日期变量,那里 FreeMarker 不能决定变量是否存储的是日期部分(年,月,日),仍是时间部分(时,分,秒,毫秒), 仍是二者都有。这种状况下,当你编写如 ${lastUpdated?string.short} ,或简 单的 ${lastUpdated} 时 FreeMarker 不知道如何来显示日期,所以模板会停止执行并抛 出错误。要阻止这些发生,你可使用内建函数 ?date , ?time 和 ?datetime 来帮助 FreeMarker。好比${lastUpdated?datetime?string.short} 。要询问程序员 数据模型中肯定的变 量是否 有这个问 题,或通 常使用 内建函数 ?date , ?time 和 ?datetime 来处理。 要代替使用预约义的格式,你可使用 ?string(pattern_string) 来精确指定 格式的模式。这个模式使用 Java 日期格式的语法。好比: ${lastUpdated?string("yyyy-MM-ddHH:mm:ss zzzz")} ${lastUpdated?string("EEE, MMM d,''yy")} ${lastUpdated?string("EEEE, MMMM dd,yyyy, hh:mm:ss a '('zzz')'")} 将会输出: 2003-04-08 21:24:44 Pacific Daylight Time Tue, Apr 8, '03 Tuesday, April 08, 2003, 09:24:44 PM (PDT) 注意: 不像预约义 格式 ,你不 能和 精确 的给 定模式 使用 内建 函数 ?date , ?time 和 ?datetime ,由于使用这个模式你就告诉 FreeMarker 来显示哪部分的日期。然而, FreeMarker 将盲目地信任你,若是你显示的部分不存在于变量中,因此你能够显示“干扰”。 好比 ${openingTime?string("yyyy-MM-dd hh:mm:ss a")} , 而 openingTime 中只存储了时间,将会显示1970-01-01 09:24:44 PM 。 定义模式的字符串也能够是 "short" , "medium" , "short_medium" 等。这和 你使 用 预 定 义 格 式 语 法 :someDate?string("short") 和 someDate?string.short 是相同的。 也能够参考:模板开发指南/模板/插值中的日期部分。 1.3.2 date ,time ,datetime (当使用日期值时) 这些内建函数用来指定日期变量中的哪些部分被使用: date :仅仅年,月和日的部分被使用。 ime :仅仅时,分,秒和毫秒的部分被使用。 datetime :日期和时间量部分都使用。 在最佳状况下,你不须要使用这些内建函数。不幸的是,因为 Java 平台上的技术限制, FreeMarker 有时不能发现日期中的哪一部分在使用(也就是说,仅仅年+月+日在使用,或仅 仅时+分+秒+毫秒在使用,或两种都用);询问程序员哪些变量会有这个问题。若是 FreeMarker 不得不执行须要这些信息的操做-好比用文本显示日期-可是它不知道哪一部分在使用,它会 以错误来停止运行。这就是你不得不使用内建函数的时候了。好比,假设 openingTime 是一个有这样问题的变量: <#assign x = openingTime> <#-- noproblem can occur here --> ${openingTime?time} <#-- without ?timeit would fail --> <#-- For the sake of betterunderstanding, consider this: --> <#assign openingTime = openingTime?time> ${openingTime} <#-- this will work now--> 这些函数的另一种用法:来截短日期。好比: Last updated: ${lastUpdated} <#-- assumethat lastUpdated is a date-time value --> Last updated date: ${lastUpdated?date} Last updated time: ${lastUpdated?time} 将会输出这样的东西: Last updated: 04/25/2003 08:00:54 PM Last updated date: 04/25/2003 Last updated time: 08:00:54 PM 若是 ? 的左边是字符串,那么这些内建函数会将字符串转换为日期变量。(参考处理字 符串的内建函数 date) 1.3.3 iso_... 内建函数族 这些内建函数转换日期,时间或时间日期值到字符串,并遵循 ISO 8601 的扩展格式。 这些 内 建 函 数 有 很 多 表 形 式 : iso_utc , iso_local , iso_utc_nz , iso_local_nz , iso_utc_m ,iso_utc_m_nz 等。名称的构成由下列单词顺序组 成,每部分由一个_(下划线)分隔开: 1. iso (必须的) 2. 是 utc 或 local 的两者之一(必须的(除了给定一个参数,这个后面再来讲)):来 指定你想根据 UTC 来打印日期或根据当前时区来打印。当前时区是根据 FreeMarker 的 设置项 time_zone 来肯定的,它一般是由程序员在模板外配置的(固然它也能够在 模板内设置,好比使用 <#setting time_zone="America/New_York"> )。 3. h, m 或 ms (可选的):时间部分的精度。当忽略的时候,就默认设置到秒的精度(比 如 12:30:18 )。 h 表示小时的精度(好比 12 ), m 表示分钟的精度(好比 12:30 ), ms 就表示毫秒的精度( 12:30:18.25,这里表示 250 毫秒)。要注意当使用 ms 时, 毫秒会显示为百分制的形式(遵循标准)并且不会去尾到 0 秒。所以,若是毫秒的部分 变成 0 的话,整个的毫秒的部分就会被忽略掉了。同时也要注意毫秒的部分是由一个点 来分隔的,而不是逗号(遵循 Web 约定和 XML Schema 的日期/时间格式)。 4. nz (可选的):若是有的话,时区偏移(好比 +02:00 或 -04:30 或 Z )就不会显示 出来了。不然是会显示出来的,仅仅对日期值有效(由于有时区偏移的日期在 ISO 8601:2004 中没有出现)。从 FreeMarker2.3.19 版开始,出于遵照 XML Schema 的日期/ 时间格式的考虑,偏移一般包含分钟。 示例: <#assign x = openingTime> <#-- noproblem can occur here --> ${openingTime?time} <#-- without ?timeit would fail --> <#-- For the sake of betterunderstanding, consider this: --> <#assign openingTime =openingTime?time> ${openingTime} <#-- this will work now--> Last updated: ${lastUpdated} <#-- assumethat lastUpdated is a date-time value --> Last updated date: ${lastUpdated?date} Last updated time: ${lastUpdated?time} Last updated: 04/25/2003 08:00:54 PM Last updated date: 04/25/2003 Last updated time: 08:00:54 PM 可能输出为(基于当前的时间和时区): <#assign aDateTime = .now> <#assign aDate = aDateTime?date> <#assign aTime = aDateTime?time> Basic formats: ${aDate?iso_utc} ${aTime?iso_utc} ${aDateTime?iso_utc} Different accuracies: ${aTime?iso_utc_ms} ${aDateTime?iso_utc_m} Local time zone: ${aDateTime?iso_local} 可能输出为(基于当前的时间和时区): Basic formats: 2011-05-16 21:32:13Z 2011-05-16T21:32:13Z Different accuracies: 21:32:13.868Z 2011-05-16T21:32Z Local time zone: 2011-05-16T23:32:13+02:00 还有另一组 iso_... 内建函数形式,你可从名称中以忽略掉 local 或 utc ,但 是要指定时区做为内建函数的参数。好比 <#assign aDateTime = .now> ${aDateTime?iso("UTC")} ${aDateTime?iso("GMT-02:30")} ${aDateTime?iso("Europe/Rome")} The usual variations are supported: ${aDateTime?iso_m("GMT+02")} ${aDateTime?iso_m_nz("GMT+02")} ${aDateTime?iso_nz("GMT+02")} 可能输出为(基于当前的时间和时区) 2011-05-16T21:43:58Z 2011-05-16T19:13:58-02:30 2011-05-16T23:43:58+02:00 The usual variations are supported: 2011-05-16T23:43+02:00 2011-05-16T23:43 2011-05-16T23:43:58 若是该时区参数不能被解释,那么模板处理就会出错而且终止。 参数也能够是 java.util.TimeZone 对象类型(会返回 Java 中方法或在数据模 型中的值),而不只仅是字符串。 1.4 处理布尔值的内建函数 1.4.1 string (当被用做是布尔值时) 转换布尔值为字符串 转换布尔值到字符串。你也以两种方式来使用: 以 foo?string :这样会使用表明 true 和 false 值的默认字符串来转换布尔值为字符 串。默认状况,true 被翻译为 "true" ,而 false 被翻译为 "false" 。若是你用 FreeMarker 来生成源代码,这是颇有用的,由于这个值不是对本地化(语言,国家)敏感的。为了改变 这些默认的字符串,你可使用 boolean_format 设置。注意,若是变量是多类型的 变量,也就是有布尔值和字符串,那么变量的字符串值会被返回。 以 foo?string("yes", "no") :若是布尔值是 true,这会返回第一个参数(这 里是: "yes" ),不然就返回第二个参数(这里是: "no" )。注意返回的的值是一个字符 串;若是参数是数字类型,首先它会被转换成字符串。 1.5 处理序列的内建函 数 1.5.1 first 第一个子变量 序列的第一个子变量。若是序列为空,那么模板处理将会停止。 1.5.2 last 最后一个子变量 序列的最后一个子变量。若是序列为空,那么模板处理将会停止。 2011-05-16T21:43:58Z 2011-05-16T19:13:58-02:30 2011-05-16T23:43:58+02:00 The usual variations are supported: 2011-05-16T23:43+02:00 2011-05-16T23:43 2011-05-16T23:43:58 1.5.3 seq_contanis 序列包含… 注意: 这个内建函数从 FreeMarker 2.3.1 版本开始可用。而在 2.3 版本中不存在。 注意: seq_ 前缀在这个内建函数中是须要的,用来和contains 区分开。 contains 函 数用来在字符串中查找子串(由于变量能够同时看成字符串和序列)。 辨别序列中是否包含指定值。它包含一个参数,就是来查找的值。好比: <#assign x = ["red", 16,"blue", "cyan"]> "blue":${x?seq_contains("blue")?string("yes", "no")} "yellow":${x?seq_contains("yellow")?string("yes", "no")} 16:${x?seq_contains(16)?string("yes", "no")} "16":${x?seq_contains("16")?string("yes", "no")} 输出是: "blue": yes "yellow": no 16: yes "16": no 为了查找值,这个函数使用了 FreeMarker 的比较规则(就像你使用的 == 运算符),除 了比较两个不一样类型的值,或 FreeMarker 不支持的类型来比较,其余都不会引发错误,只 是为认为两个值不相等。所以,你可使用它来查找标量值(也就是字符串,数字,布尔值, 或日期/时间类型)。对于其余类型结果一般都是 false 。 对于容错性,这个函数还对 collections 起做用。 1.5.4 seq_index_of 第一次出现… 时的位置 注意: 这个内建函数从 FreeMarker 2.3.1 版本开始可用。而在 2.3 版本中不存在。 注意: seq_ 前缀在这个内建函数中是须要的,用来和index_of 区分开。 index_of 函 数用来在字符串中查找子串(由于变量能够同时看成字符串和序列)。 返回序列中第一次出现该值时的索引位置,若是序列不包含指定的值时返回 -1 。要查 找的值做为第一个参数。好比这个模板: <#assign colors = ["red","green", "blue"]> ${colors?seq_index_of("blue")} ${colors?seq_index_of("red")} ${colors?seq_index_of("purple")} 将会输出: 2 0 -1 为了查找值,这个函数使用了 FreeMarker 的比较规则(就像你使用的 == 运算符),除 了比较两个不一样类型的值,或 FreeMarker 不支持的类型来比较,其余都不会引发错误,只 是为认为两个值不相等。所以,你可使用它来查找标量值(也就是字符串,数字,布尔值, 或日期/时间类型)。对于其余类型结果一般是 -1 。 搜索开始的地方能够由第二个可选的参数来肯定。若是在同一个序列中相同的项能够多 次出现时,这是颇有用的。第二个参数的数值没有什么限制:若是它是负数,那么就和它是 零的效果同样,而若是它是比序列长度还大的数,那么就和它是序列长度值的效果同样。小 数值会被切成整数。好比: <#assign names = ["Joe","Fred", "Joe", "Susan"]> No 2nd param:${names?seq_index_of("Joe")} -2: ${names?seq_index_of("Joe",-2)} -1: ${names?seq_index_of("Joe",-1)} 0: ${names?seq_index_of("Joe",0)} 1: ${names?seq_index_of("Joe",1)} 2: ${names?seq_index_of("Joe",2)} 3: ${names?seq_index_of("Joe",3)} 4: ${names?seq_index_of("Joe",4)} 将会输出: No 2nd param: 0 -2: 0 -1: 0 0: 0 1: 2 2: 2 3: -1 4: -1 1.5.5 seq_last_index_of 最后一次出现.. 的位置 注意: 这个内建函数从 FreeMarker 2.3.1 版本开始可用。而在 2.3 版本中不存在。 注意: seq_ 前缀在这个内建函数中是须要的,用来和last_index_of 区分开。 last_index_of 用于在字符串中搜索子串(由于一个变量能够同时是字符串和序列)。 返回序列中最后一次出现值的索引位置,,若是序列不包含指定的值时返回 -1 。也就是 说,和 seq_index_of 相同,只是在序列中从最后一项开始向前搜索。它也支持可选的 第二个参数来肯定从哪里开始搜索的索引位置。好比: <#assign names = ["Joe","Fred", "Joe", "Susan"]> No 2nd param:${names?seq_index_of("Joe")} -2: ${names?seq_index_of("Joe",-2)} -1: ${names?seq_index_of("Joe",-1)} 0: ${names?seq_index_of("Joe",0)} 1: ${names?seq_index_of("Joe",1)} 2: ${names?seq_index_of("Joe",2)} 3: ${names?seq_index_of("Joe",3)} 4: ${names?seq_index_of("Joe",4)} 将会输出这个: No 2nd param: 2 -2: -1 -1: -1 0: 0 1: 0 2: 2 3: 2 4: 2 1.5.6 reverse 反转序列 序列的反序形式。 1.5.7 size 序列大小 序列中子变量的数量(做为一个数值)。假设序列中至少有一个子变量,那么序列 s 中 最大的索引是 s?size - 1 (由于第一个子变量的序列是 0)。 1.5.8 sort 排序 以升序方式返回。(要使用降序排列时,使用它以后还要使用 reverse 内建函数)这 仅在子变量都是字符串时有效,或者子变量都是数字,或者子变量都是日期值(日期,时间, 或日期+时间),或者全部子变量都是布尔值时(从 2.3.17 版本开始)。若是子变量是字符串, 它使用本地化(语言)的具体单词排序(一般是大小写不敏感的)。好比: <#assign ls = ["whale","Barbara", "zeppelin", "aardvark", "beetroot"]?sort> <#list ls as i>${i} </#list> 将会打印(至少是 US 区域设置): aardvark Barbara beetroot whale zeppelin 1.5.9 sort_by 以… 来排序 返回由给定的哈希表子变量来升序排序的哈希表序列。(要降序排列使用这个内建函数 后还要使用 reverse 内建函数)这个规则和内建函数 sort 是同样的,除了序列中的子 变量必须是哈希表类型,并且你不得不给哈希变量的命名,那会用来决定排序顺序。好比: <#assign ls = [ {"name":"whale","weight":2000}, {"name":"Barbara","weight":53}, {"name":"zeppelin","weight":-200}, {"name":"aardvark","weight":30}, {"name":"beetroot","weight":0.3} ]> Order by name: <#list ls?sort_by("name") asi> - ${i.name}: ${i.weight} </#list> Order by weight: <#list ls?sort_by("weight") asi> - ${i.name}: ${i.weight} </#list> 将会打印(至少是 US 区域设置): Order by name: - aardvark: 30 - Barbara: 53 - beetroot: 0.3 - whale: 2000 - zeppelin: -200 Order by weight: - zeppelin: -200 - beetroot: 0.3 - aardvark: 30 - Barbara: 53 - whale: 2000 若是你用来排序的子变量的层次很深(也就是说,它是子变量的子变量的子变量,以此 类推),那么你可使用序列来做为参数,它指定了子变量的名字,来向下引导所需的子变 量。好比: <#assign members = [ {"name": {"first":"Joe", "last": "Smith"}, "age": 40}, {"name": {"first":"Fred", "last": "Crooger"}, "age": 35}, {"name": {"first":"Amanda", "last": "Fox"}, "age":25}]> Sorted by name.last: <#list members?sort_by(['name', 'last'])as m> - ${m.name.last}, ${m.name.first}: ${m.age}years old </#list> 将会打印(至少是 US 区域设置): Sorted by name.last: - Crooger, Fred: 35 years old - Fox, Amanda: 25 years old - Smith, Joe: 40 years old 1.5.10 chunk 区块 注意: 这个内建函数从 FreeMarker 2.3.3 版本之后可用。 这个 内建 函数 分割 序列 到多 个大 小为 函数 的第 一个 参数 给定 的序 列( 就 像 mySeq?chunk(3) )。结果是包含这些序列的一个序列。最后一个序列可能比给定的大 小要小,处分第二个参数也给定了(好比 mySeq?chunk(3, '-') ),那个就是用来填 充最后一个序列,以达到给定的大小。好比: <#assign seq = ['a', 'b', 'c', 'd', 'e','f', 'g', 'h', 'i', 'j']> <#list seq?chunk(4) as row> <#list row as cell>${cell}</#list> </#list> <#list seq?chunk(4, '-') as row> <#list row as cell>${cell}</#list> </#list> 这会输出: a b c d e f g h i j a b c d e f g h i j - - 这个函数一般在输出的序列中使用表格/柱状的格式。当被用于 HTML 表格时,第二个 参数一般是 "\xA0" (也就是不换行的空格代码,也就是咱们所知的“nbsp”),因此空 TD 的边界就不会不显示。 第一个参数必须是一个数字,并且至少是 1.若是这个数字不是整数,那么它会被静默地 去掉小数部分(也就是说 3.1 和 3.9 都会被规整为 3)。第二个参数能够是任意类型的值。 1.6 处理哈希表的内建函数 1.6.1 keys 键的集合 一个包含哈希表中查找到的键的序列。注意并非全部的哈希表都支持这个(询问程序 员一个指定的哈希表是否容许这么操做)。 <#assign h ={"name":"mouse", "price":50}> <#assign keys = h?keys> <#list keys as key>${key} = ${h[key]};</#list> 输出: name = mouse; price = 50; 由于哈希表一般没有定义子变量的顺序,那么键名称的返回顺序就是任意的。然而,一 些哈希表维持一个有意义的顺序(询问程序员指定的哈希表是不是这样)。好比,由上述 {...} 语法建立的哈希表保存了和你指定子变量相同的顺序。 1.6.2 值的集合 一个包含哈希表中子变量的序列。注意并非全部的哈希表都支持这个(询问程序员一 个指定的哈希表是否容许这么操做)。 至于返回的值的顺序,和函数 keys 的应用是同样的;看看上面的叙述就好了。 1.7 处理节点(XML )的内建函数 注意由这些内建函数返回的变量是由用于节点变量的实现生成的。意思就是返回的变量 能够有更多的特性,附加于它这里的状态。好比,由内建函数 children 返回的序列和 XML DOM 节点也能够被用做是哈希表或字符串,这在第三部分 XML 处理指南中有解释。 1.7.1 children 子节点序列 一个包含该节点全部子节点(也就是直接后继节点)的序列。 XML:这和特殊的哈希表的键 * 几乎是同样的。除了它返回全部节点,而不可是元素。 因此可能的子节点是元素节点,文本节点,注释节点,处理指令节点等,并且还多是属性 节点。属性节点排除在序列以外。 1.7.2 parent 父节点 在节点树中,返回该节点的直接父节点。根节点没有父节点,因此对于根节点,表达式 node?parent?? 的值就是 false 。 XML:注意经过这个函数返回的值也是一个序列(当你编写 someNode[".."] 时, 和 XPath 表达式 .. 的结果是同样的)。也要注意属性节点,它返回属性所属的元素节点,尽 管属性节点不被算做是元素的子节点。 1.7.3 root 根节点 该节点所属节点树的根节点。 XML:根据 W3C,XML 文档的根节点不是最顶层的元素节点,而是文档自己,是最高元 素的父节点。例如,若是你想获得被称为是 foo 的 XML(所谓的“文档元素”,不要和“文 档”搞混了)的最高元素,那么你不得不编写 someNode?root.foo 。若是你仅仅写了 someNode?root ,那么你获得的是文档自己,而不是文档元素。 1.7.4 ancestors 祖先节点 一个包含全部节点祖先节点的序列,以直接父节点开始,以根节点结束。这个函数的结 果也是一个方法,你能够用它和元素的彻底限定名来过滤结果。好比以名称 section 用 node?ancestors("section") 来得到全部祖先节点的序列, 1.7.5 node_name 节点名称 当被“访问”时,返回用来决定哪一个用户自定义指令来调用控制这个节点的字符串。可 以参见 visit 和 recurse 指令。 XML:若是节点是元素或属性,那么字符串就会是元素或属性的本地(没有前缀)名字。 不然,名称一般在节点类型以后以 @ 开始。能够参见 XML 处理指南中 2.2 节的形式化描述。 要注意这个节点名称与在 DOM API 中返回的节点名称不一样;FreeMarker 节点名称的目标是 给要处理节点的用户自定义指令命名。 1.7.6 node_type 节点类型 描述节点类型的字符串。FreeMarker 没有对节点类型定义准确的含义;它依赖于变量是 怎么建模的。也可能节点并不支持节点类型。在这种情形下,该函数就返回未定义值,因此 你就不能使用返回值。(你能够用 node?node_type?? 继续检查一个节点是不是支持类 型属性) XML : 可 能 的 值 是"attribute" , "text" , "comment" , "document_fragment" ,"document" , "document_type" , "element", "entity" ,"entity_reference" , "notation" , "pi" 。注意没有 "cdata" 类型,由于 CDATA 被认为是普通文本元素。 1.7.7 node_namespace 节点命名空间 返回节点命名空间的字符串。FreeMarker 没有为节点命名空间定义准确的含义;它依赖 于变量是怎么建模的。也可能节点没有定义任何节点命名空间。这种情形下,该函数应该返 回未定义的变量(也就是 node?node_namespace?? 的值是 false ),因此你不能使 用这个返回值。 XML : 这 种 情 况 下 的 XML , 就 是 XML 命 名 空 间 的 URI ( 比 如 "http://www.w3.org/1999/xhtml" )。若是一个元素或属性节点没有使用 XML 命名空间,那么这个函数就返回一个空字符串。对于其余 XML 节点这个函数返回未定义的 变量。 1.8 不多使用的和专家级的内建函数 这些是你一般状况下不该该使用的内建函数,可是在特殊状况下(调试,高级宏)它们 会有用。若是你须要在普通页面模板中使用这些函数,你可能会从新访问数据模型,因此你 不要使用它们。 1.8.1 byte ,double ,float ,int ,long ,short 返回一个包含原变量中相同值的 SimpleNumber ,可是在内部表示值中使用了 java.lang.Type 。若是方法被重载了,这是有用的,或者一个 TemplateModel 解包器在自动选择适合的 java.lang.* 类型有问题时。注意从 2.3.9 版本开始,解包器 有本质上改进,因此你将基本不会使用到这些内建函数来转换数字类型了,除非在重载方法 调用中来解决一些含糊的东西。 内建函数 long 也能够用于日期, 时间和时 间日期 类型的 值来获取 返回为 java.util.Date.getTime() 的值。若是你不得不调用使用long 类型时间戳的 Java 方法时,这是很是有用的。这个转换不是自动进行的。 1.8.2 number_date ,number_to_time ,number_to_datetime 它们被用来转换数字(一般是 Java 的 long 类型)到日期,时间或时间日期类型。这 就使得它们和 Java 中的 new java.util.Date(long) 是一致的。那也就是说,如今 数字能够被解释成毫秒数进行参数传递。数字能够是任意内容和任意类型,只要它的值能够 认为是 long 就行。若是数字不是完整的,那么它就会根据“五入”原则进行进位。这个 转换不是自动进行的。 示例: ${1305575275540?number_to_datetime} ${1305575275540?number_to_date} ${1305575275540?number_to_time} 输出就会是像这样的(基于当前的本地化设置和时区): May 16, 2011 3:47:55 PM May 16, 2011 3:47:55 PM 1.8.3 eval 求值 这个函数求一个做为 FTL 表达式的字符串的值。好比 "1+2"?eval 返回数字 3。 1.8.4 has_content 是否有内容 若是变量(不是 Java 的 null )存在并且不是“空”就返回 true ,不然返回 false 。 “空”的含义靠具体的情形来决定。它是直观的常识性概念。下面这些都是空:长度为 0 的字符串,没有子变量的序列或哈希表,一个已经超过最后一项元素的集合。若是值不是字 符串,序列,哈希表或集合,若是它是数字,日期或布尔值(好比 0 和 false 是非空的), 那么它被认为是非空的,不然就是空的。注意当你的数据模型实现了多个模板模型接口,你 可能会获得不是预期的结果。然而,当你有疑问时你一般可使用 expr!?size > 0 或 expr!?length > 0 来代替 expr?has_content 。 这个函数是个特殊的函数,你可使用像默认值操做符那样的圆括号手法。也就是说, 你可 以 编 写product.color?has_content 和 (product.color)?has_content 样的代码。第一个没有控制当product 为空 的情形,而第二个控制了。 1.8.5 interpret 将字符串解释为 FTL 模板 这个函数解释字符串做为 FTL 模板,并且返回一个用户自定义指令,也就是当应用于任 意代码块中时,执行模板就像它当时被包含同样。例如: <#assign x=["a","b", "c"]> <#assign templateSource =r"<#list x as y>${y}</#list>"> <#-- Note: That r was needed so that the${y} is not interpreted above --> <#assign inlineTemplate = templateSource?interpret> <@inlineTemplate /> 输出为: abc 正如你看到的, inlineTemplate 是用户自定义指令,也就是当被执行时,运行当 时使用 interpret 函数生成的模板。 你也能够在两个元素的序列中应用这个函数。这种状况下序列的第一个元素是模板源代 码,第二个元素是内联模板的名字。在调试时它能够给内联模板一个肯定的名字,这是颇有 用的。因此你能够这么来写代码: <#assign inlineTemplate = [templateSource, "myInlineTemplate"]?interpret> 在上述的模板中,要注意给内联模板一个名字没有及时的效果,它仅仅在你获得错误报 告时能够获得额外的信息。 1.8.6 is_... 判断函数族 这些内建函数用来检查变量的类型,而后根据类型返回或。下面是 is_... 判断函数 族的列表: 内建函数 若是值是… 时返回 true is_string 字符串 is_number 数字 is_boolean 布尔值 is_date 日期(全部类型:仅日期,仅时间和时间日期) is_method 方法 is_transform 变换 is_macro 宏 is_hash 哈希表 is_hash_ex 扩展的哈希表(也就是支持 ?keys 和 ?values ) is_sequence 序列 is_collection 集合 is_enumerable 序列或集合 is_indexable 序列 is_directive 指令的类型(好比宏,或 TemplateDirectiveModel , TemplateTransformModel 等) is_node 节点 1.8.7 namespace 命名空间 这个函数返回和宏变量关联的命名空间(也就是命名空间的入口哈希表)。你只能和宏 一块儿来用它。 1.8.8 new 建立TemplateModel 实现 这是用来建立一个肯定 TemplateModel 实现的变量的内建函数。 在 ? 的左边你能够指定一个字符串,是 TemplateModel 实现类的彻底限定名。结 果是调用构造方法生成一个方法变量,而后将新变量返回。 好比: 对于更多的关于构造方法参数被包装和如何选择重载的构造方法信息,请阅读:程序开 发指南/其它/Bean 包装器部份内容。 这个内建函数能够是出于安全考虑的,由于模板做者能够建立任意的 Java 对象,只要 它们实现了 TemplateModel 接口,而后来使用这些对象。并且模板做者能够触发没有 实现 TemplateModel 接口的类的静态初始化块。你能够(从 FreeMarker 2.3.17 版开始) 限制 这 个 内 建 函 数 对 类 的 访 问 , 通 过 使 用 Configuration.setNewBuiltinClassResolver(TemplateClassRes olver) 或设置new_builtin_class_resolver 。参考 Java API 文档来获取详细信 息。若是您容许并非很可靠的用户上传模板,那么你必定要关注这个问题。 <#-- Creates an user-defined directivebe calling the parameterless constructor of the class--> <#assign word_wrapp = "com.acmee.freemarker.WordWrapperDirective"?new()> <#-- Creates an user-defined directivebe calling the constructor with one numerical argument--> <#assign word_wrapp_narrow = "com.acmee.freemarker.WordWrapperDirective"?new(40)> 对于更多的关于构造方法参数被包装和如何选择重载的构造方法信息,请阅读:程序开 发指南/其它/Bean 包装器部份内容。 这个内建函数能够是出于安全考虑的,由于模板做者能够建立任意的 Java 对象,只要 它们实现了 TemplateModel 接口,而后来使用这些对象。并且模板做者能够触发没有 实现 TemplateModel 接口的类的静态初始化块。你能够(从 FreeMarker 2.3.17 版开始) 限制 这 个 内 建 函 数 对 类 的 访 问 , 通 过 使 用 Configuration.setNewBuiltinClassResolver(TemplateClassRes olver) 或设置new_builtin_class_resolver 。参考 Java API 文档来获取详细信 息。若是您容许并非很可靠的用户上传模板,那么你必定要关注这个问题。 --------------------- 做者:R鲜森 来源:CSDN 原文:https://blog.csdn.net/sinat_32366329/article/details/78888222 版权声明:本文为博主原创文章,转载请附上博文连接!