当前位置: 首页 > news >正文

freemarker模板学习笔记

文章目录

  • freemarker常用指令
    • if-elseif-else指令
    • switch, case, default, break指令
    • list, else, items, sep, break 指令
      • <#list>指令语法
      • <#else> 指令
      • <#items> 指令
      • <#sep> 指令
      • <#break> 指令
    • include 指令
      • <#include> 基础知识
      • <#include> 带 * 的 path
    • import 指令
    • assign 指令
    • 自定义指令
      • 参数
      • 嵌套内容
      • 宏和循环变量
  • freemarker内置函数
    • 字符串内置函数
    • 数字内置函数
    • 哈希表内置函数
    • 序列内置函数
    • 循环变量内置函数
  • 示例
  • 参考文档:[https://www.hxstrive.com/subject/freemarker/33.htm](https://www.hxstrive.com/subject/freemarker/33.htm)

freemarker常用指令

if-elseif-else指令

语法

<#if condition>...
<#elseif condition2>...
<#elseif condition3>...
<#else>...
</#if>

elseif和else是可选的

<#if condition>
</#if>

switch, case, default, break指令

语法

<#switch value><#case refValue1>...<#break><#case refValue2>...<#break><#case refValuen>...<#break><#default>...
</#switch>

list, else, items, sep, break 指令

<#list>指令语法

形式1:

<#list sequence as item>Part repeated for each item
<#else>Part executed when there are 0 items
</#list>
  • <#else>:是可选的,而且仅仅从 FreeMarker 2.3.23 版本开始支持。
  • sequence:将我们想要迭代的项,算作是序列或集合的表达式
  • item:循环变量的名称 (不是表达式)

形式2

<#list sequence>Part executed once if we have more than 0 items<#items as item>Part repeated for each item</#items>Part executed once if we have more than 0 items
<#else>Part executed when there are 0 items
</#list>
  • <#else>:是可选的,而且仅仅从 FreeMarker 2.3.23 版本开始支持。
  • sequence:将我们想要迭代的项,算作是序列或集合的表达式
  • <#items>:该标签的作用是替代 的 “as item”部分
  • item:循环变量 的名称 (不是表达式)

<#else> 指令

注意:在 list 中的 else 仅从 FreeMarker 2.3.23 版本开始支持。

当没有迭代项时(即 users 为空列表),才使用 else 指令, 可以输出一些特殊的内容而不只是空在那里

<#items> 指令

注意:<#items> 从 FreeMarker 2.3.23 版本开始存在

如果不得不在第一列表项之前或在最后一个列表项之后打印一些东西, 那么就要使用 items 指令,但至少要有一项。

<#sep> 指令

注意:sep 从 FreeMarker 2.3.23 版本开始存在。
当不得不显示介于每个迭代项 (但不能在第一项之前或最后一项之后) 之间的一些内容时,可以使用 sep。

eg:
<#list users as user>${user}<#sep>, </#list>
输出:
Joe, Kate, Fred

<#break> 指令

可以使用 break 指令在迭代的任意点退出。

include 指令

<#include> 基础知识

您可以使用 include 指令在你的模板中插入另外一个 FreeMarker 模板文件,将在 include 指令出现的位置插入的被包含模版的内容。

<#include path>
<!-- 或 -->
<#include path options>
  • path: 要包含模版文件的路径,可以是一个字符串表达式。例如:profile.baseDir + “/menu.ftl”
  • options: 可选的,一个或多个选项: encoding=encoding, parse=parse
  • encoding:被包含文件从包含它的文件继承的编码方式 (实际就是字符集),除非你用这个选项来指定编码方式。 合法的名字有:ISO-8859-2,UTF-8,Shift_JIS,Big5,EUC-KR,GB2312。注意:编码名称要和 java.io.InputStreamReader 中支持的那些一致 (对于Java API 1.3版本:MIME 希望的字符集是从IANA字符集注册处得到的)
  • parse:如果它为 true,那么被包含的文件将会当作FTL来解析,否则整个文件将被视为简单文本 (也就是说不会在其中查找 FreeMarker 的结构)。如果你忽略了这个选项,那么它默认是 true。
  • ignore_missing:当为 true,模板引用为空时压制错误,而 <#include …> 不会输出任何东西。当为 false 时,如果模板不存在, 那么模板处理就会发生错误并停止。如果忽略这个选项,那么它的默认值是 false。

<#include> 带 * 的 path

FreeMaker 的 include 指令 path 属性可以使用 ,星号()被解释为 “当前目录或其他任意它的父目录”

import 指令

<#import> 指令用来引入一个库。它将根据指定的 hash 创建一个新的空命名空间, 然后在那个命名空间中执行给定 path 参数中的模板,path 指定模板的变量 、宏、函数等放入指定的命名空间。 然后就可以使用“新命名空间.属性”的方式访问导入模版中的变量。

<#import path as hash>
  • path:模板的路径如:profile.baseDir + “/menu.ftl”。模版路径可以是一个相对路径,比如 “foo.ftl” 和 “…/foo.ftl”,或者是像 “/foo.ftl” 一样的绝对路径。 相对路径是相对于使用 import 指令模板的目录。 绝对路径是程序员配置 FreeMarker 时定义的相对于根路径 (通常指代"模板的根目录") 的路径。通常使用 / (斜杠) 来分隔路径组成, 而不是 (反斜杠)。如果你从你本地的文件系统中加载模板, 那么它使用反斜杠 (比如在Windows环境下),FreeMarker 将会自动转换它们。
  • hash:访问命名空间的哈希表变量不带引号的名字

assign 指令

使用 <#assign> 指令你可以创建一个新的变量,或者替换一个已经存在的变量。

注意:仅仅顶级变量可以被创建/替换,也就是说你不能创建/替换 user.name,但是可以整体替换 user。

<#assign name1=value1 name2=value2 ... nameN=valueN>
<!-- 或 -->
<#assign same as above... in namespacehash>
<!-- 或 -->
<#assign name>capture this
</#assign>
<!-- 或 -->
<#assign name in namespacehash>capture this
</#assign>
  • name:变量的名字,是一个字符串
  • =:赋值操作符。它也可以是一个简写的赋值操作符 (从 FreeMarker 2.3.23 版本开始): ++,–, +=,-=, *=,/= 或 %=。比如 <#assign x++> 和 <#assign x = x + 1> 是一样的,并且 <#assign x += 2> 和 <#assign x = x + 2> 是相同的。 请注意,++ 通常意味着算术加法 (对于非数字将会失败),不像 + 或 += 可以进行字符连接等重载操作。
  • value: 变量存储的值,可以是具体指,也可以是表达式。
  • namespacehash:通过 import 指令导入库,为库的命名空间创建的哈希表。如:<#assign date=“2020-06-20” in my>

自定义指令

macro 指令来自定义指令
在 macro 指令中,宏名称的后面位置是用来定义参数的

<#macro greet><font>Hello Joe!</font>
</#macro>

macro 指令自身不输出任何内容,它只是用来创建宏变量,所以就会有一个名为 greet 的宏变量。在 <#macro greet> 和 </#macro> 之间的内容 (称为宏定义体) 将会在使用该宏变量作为指令时执行。可以在 FTL 标记中通过 <@宏变量名></@宏变量名> 的方式来使用自定义指令。因此,就可以这样来使用 greet 宏变量:

<@greet></@greet>

参数

在 macro 指令中,宏名称的后面位置是用来定义参数的。

<#macro greet person><font>Hello ${person}!</font>
</#macro>
<@greet person="Fred"/>
<@greet person="Batman"/>

嵌套内容

自定义指令可以嵌套内容(使用 <#nested> 指令引用宏指令开始和结束标签中间的内容),和预定义指令相似:<#if …>nested content</#if>。

<#macro border><table border=4 cellspacing=0 cellpadding=4><tr><td><#nested></td></tr></table>
</#macro>
<@border>The bordered text</@border>

宏和循环变量

像 list 这样的预定义指令可以使用循环变量,而对于预定义指令 (如list),当调用指令时,循环变量的 name 是给定的,比如 <#list foos as foo>…</#list> 中的 foo,变量 value 的设置是由指令本身完成的。

<#macro repeat count><#list 1..count as x><#nested x, x/2, x==count></#list>
</#macro><@repeat count=4 ; c, halfc, last>${c}. ${halfc}<#if last> Last!</#if>
</@repeat>

freemarker内置函数

字符串内置函数

  • boolean:将字符串转换成布尔值
  • cap_first:字符串中的首单词的首字母大写
  • capitalize:字符串中所有单词的首字母大写
  • chop_linebreak: 在末尾没有换行符的字符串,那么可以换行,否则不改变字符串
  • contains:判断字符串中是否包含给定的子字符串
<#if "piceous"?contains("ice")>It contains "ice"</#if>
  • date, time, datetime:字符串转换成日期值,时间或日期-时间值
  • ends_with:返回是否这个字符串以参数中指定的子串结尾
<#if "ahead"?ends_with("head")>字符串以head结尾
<#else>不是以head结尾
</#if>
<#if "head"?ends_with("head")>字符串以head结尾
<#else>不是以head结尾
</#if>
  • ensure_ends_with:如果字符串没有以第一个参数指定的子串结尾, 那么就会将它加到字符串后面,否则返回原字符串
${"foo"?ensure_ends_with("/")}
${"foo/"?ensure_ends_with("/")}
  • ensure_starts_with:如果字符串没有以第一个参数指定的子串开头, 那么就会将它加到字符串开头,否则返回原字符串
  • groups:这个函数只作用于内建函数 matches 的结果
  • html:字符串按照HTML标记输出
  • index_of:返回第一次字符串中出现子串时的索引位置
${"abcabc"?index_of("bc")}
  • j_string:根据Java语言字符串转义规则来转义字符串
  • js_string:
  • json_string:根据 JSON 语言的字符串规则来转义字符串
  • keep_after:移除字符串中的一部分内容,该部分是给定子串第一次出现之前的部分
  • keep_after_last:和 keep_after 相同, 但是它会保留参数最后一次出现后的部分,而不是第一次
  • keep_before:移除字符串的一部分,该部分是从给定子串开始的部分
  • keep_before_last:和 keep_before 相同,但是保留参数最后一次出现之前的部分,而不是第一次出现之前
  • last_index_of:返回最后一次(最右边)字符串中出现子串时的索引位置
  • 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)}]
[${"abcdef"?left_pad(5)}]
[${"abcdefg"?left_pad(5)}]
[${"abcdefgh"?left_pad(5)}]
  • length:字符串中字符的数量
  • lower_case:字符串的小写形式
  • matches:字符串是否完全匹配指定的正则表达式
<#if "fxo"?matches("f.?o")>Matches.<#else>Does not match.</#if>
<#assign res = "foo bar fyo"?matches("f.?o")>
<#if res>Matches.<#else>Does not match.</#if>Matching sub-strings:
<#list res as m>
- ${m}
</#list>
  • number:字符串转化为数字格式
  • replace:用另外一个字符串来替换原字符串中出现它的部分
	
${"this is a car acarus"?replace("car", "bulldozer")}
  • right_pad:从末尾开始插入字符
  • remove_beginning:从字符串的开头移除参数中的子串
${"abcdef"?remove_beginning("abc")}
${"foobar"?remove_beginning("abc")}
  • remove_ending:从字符串的结尾移除参数中的子串
  • rtf:字符串作为富文本(RTF 文本)
  • split:它被用来根据另外一个字符串的出现将原字符串分割成字符串序列
<#list "someMOOtestMOOtext"?split("MOO") as x>
- ${x}
</#list>
  • starts_with:如果字符串以指定的子字符串开头,那么返回true
  • string:(当被用作是字符串值时) 返回字符串
<#assign x=42>
${x}
${x?string}  <#-- the same as ${x} -->
${x?string.number}
${x?string.currency}
${x?string.percent}
${x?string.computer}<#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"]}
  • substring: (已废弃) 字符串分割
  • trim:去掉字符串首尾的空格
  • uncap_first: 字符串中所有单词的首字母小写
  • upper_case:字符串的大写形式
  • url:对 URL 字符串进行转义
  • url_path:URL转义,它不转义斜杠 (/) 字符
  • word_list:提取字符串中所有单词,返回单词序列
  • xhtml:字符串作为XHTML格式文本
  • xml:字符串作为XML格式文本

数字内置函数

  • abs:返回数字的绝对值
  • c:当被用作是数字值时,将数字转换成字符串
  • is_infinite:数字是否是无限浮点数
  • is_nan:辨别数字是否是浮点数NaN
  • round, floor, ceiling:数字舍入
  • string:当用作是数字类型时,将一个数字转换成字符串
  • lower_abc:将1,2,3等,转换为字符串 “a”,“b”,“c” 等
  • upper_abc:将1,2,3等,转换为字符串 “A”,“B”,“C” 等

哈希表内置函数

  • keys:返回哈希表中所有键的序列
  • values:返回哈希表中所有子变量序列

序列内置函数

  • chunk:将序列分隔为多个序列
<#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>
  • first:序列的第一个子变量
  • join:使用给定的分隔符来连接序列中的项为一个独立的字符串
<#assign colors = ["red", "green", "blue"]>
${colors?join(", ")}
  • last:序列的最后一个子变量
  • reverse:序列的反序形式
  • seq_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")}
  • seq_index_of:返回序列中第一次出现该值时的索引位置
<#assign colors = ["red", "green", "blue"]>
${colors?seq_index_of("blue")}
${colors?seq_index_of("red")}
${colors?seq_index_of("purple")}
  • seq_last_index_of:返回序列中最后一次出现值的索引位置
<#assign names = ["Joe", "Fred", "Joe", "Susan"]>
No 2nd param: ${names?seq_last_index_of("Joe")}
-2: ${names?seq_last_index_of("Joe", -2)}
-1: ${names?seq_last_index_of("Joe", -1)}
0: ${names?seq_last_index_of("Joe", 0)}
1: ${names?seq_last_index_of("Joe", 1)}
2: ${names?seq_last_index_of("Joe", 2)}
3: ${names?seq_last_index_of("Joe", 3)}
4: ${names?seq_last_index_of("Joe", 4)}
  • size:序列中子变量的数量
  • sort:以升序方式返回序列
<#assign ls = ["whale", "Barbara", "zeppelin", "aardvark", "beetroot"]?sort>
<#list ls as i>${i} </#list>
  • sort_by:返回由给定的哈希表子变量来升序排序的哈希表序列
<#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") as i>
- ${i.name}: ${i.weight}
</#list>Order by weight:
<#list ls?sort_by("weight") as i>
- ${i.name}: ${i.weight}
</#list>

循环变量内置函数

  • counter:返回当前迭代从1开始的索引
  • has_next:判断当前迭代是否有下一个元素
<#list ['a', 'b', 'c'] as i>${i?has_next?c}
</#list>
  • index:返回当前迭代从0开始的索引
  • is_even_item:判断循环项是否是当前迭代间隔 1 的奇数项
<#list ['a', 'b', 'c', 'd'] as i>
${i?is_even_item?c}
</#list>
  • is_first:判断循环项是否是当前迭代的第一项
<#list ['a', 'b', 'c'] as i>
${i?is_first?c}
</#list>
  • is_last:判断循环项是否是当前迭代的最后一项
<#list ['a', 'b', 'c'] as i>
${i?is_last?c}
</#list>
  • is_odd_item:判断循环项是否是当前迭代间隔1的偶数项
<#list ['a', 'b', 'c', 'd'] as i>
${i?is_odd_item?c}
</#list>
  • item_cycle:循环输出指定的参数,至少指定一个参数
<#list ['a', 'b', 'c', 'd', 'e', 'f', 'g'] as i><tr class="${i?item_cycle('row1', 'row2', 'row3')}">${i}</tr>
</#list>
  • item_parity:根据奇偶返回字符串值 “odd” 或 “even”(注意大小写)
  • item_parity_cap:根据奇偶返回字符串值 “Odd” 或 “Even”(注意大小写)

示例

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>freemarker study</title></head><body><p>${"C:\\demo\\red\\index.html"}</p><p>${r"C:\demo\red\index.html"}</p><#-- <#list lists as item>${item}</#list> 遍历列表       --><#-- 生成 0 到 9 的数字序列 --><p><#list 0..9 as item>${item}<#sep>,</#list></p><#-- 生成 0 到小于 10 的数字序列 --><p><#list 0..<10 as item>${item}<#sep>,</#list></p><p><#list 0..!10 as item>${item}<#sep>,</#list></p><#-- 生成 0 到无穷大的数字序列 --><p><#list 0.. as item>${item}<#sep>,</#list></p><#-- 字符串切割 --><#assign host="https://www.hxstrive.com"><p>${host[0..6]}</p><p>${host[0..<6]}</p><p>${host[0..*100]}</p><p>${host[7..]}</p></body>
</html>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>freemarker study</title>
</head>
<body><p>常用内建函数示例:</p><#assign htmlCode="hello <lable style=\"color:red;\">world</label>"/><#assign user="administrator" />
<#--    输出html代码--><p>html=${htmlCode?html}</p>
<#--    转大写--><p>upper_case=${user?upper_case}</p>
<#--    首字母大写--><p>cap_first=${user?cap_first}</p>
<#--    长度--><p>length=${user?length}</p><p>list 标签中内置函数示例</p><#assign books=["Java","C#","C++"] />
<#--    个数--><p>size=${books?size}</p><#list books><#items as book>
<#--            下标--><p>index=${book?index}</p>
<#--            第几个--><p>counter=${book?counter}</p>
<#--            奇偶性--><p>item_parity=${book?item_parity}</p></#items></#list><p>一些内建函数需要参数来指定行为</p><#assign colors=["red","blue","green"] /><#assign flag=false />
<#--    字符判断--><p>string=${flag?string("Y","N")}</p><#list books><#items as book>
<#--            遍历--><p>item_parity=${book?item_cycle("lightRow","darkRow")}</p></#items></#list>
<#--    列表拼接字符--><p>join=${colors?join(",")}</p>
<#--    判断开始字母--><#if user?starts_with("a")><p>starts_with=${user} 以a开头</p><#else><p>starts_with=${user} 不以a开头</p></#if>
</body>
</html>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>freemarker 自定义指令</title>
</head>
<body>
<#--macro 声明宏指令 greet为宏变量 引用时使用@greet person为传入的变量--><#macro greet person><font>Hello ${person}</font></#macro><@greet person="Fred"></@greet><@greet person="Batman"></@greet>
<#--嵌套内容--><#macro border><table border="4" cellspacing="0" cellpadding="4"><tr>
<#--                nested接收传入的数据--><td><#nested></td></tr></table></#macro><@border>The bordered text</@border><#macro do_thrice><#nested><#nested><#nested></#macro><@do_thrice>Anything.</@do_thrice><@border><ul><@do_thrice><li><@greet person="Joe"></@greet></li></@do_thrice></ul></@border><#--    一个宏可以使用多个循环变量--><#macro repeat count><#list 1..count as x><#nested x, x/2,x==count></#list></#macro><@repeat count=4 ; c,halfc,last>${c}. ${halfc}<#if last> Last!</#if></@repeat>
</body>
</html>

参考文档:https://www.hxstrive.com/subject/freemarker/33.htm

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【C#编程技术总结】魔法包唤醒同一局域网设备
  • Unity解析XML开发随机名字生成模块
  • 联想泄露显示本月推出更便宜的Copilot Plus电脑
  • 虚幻引擎VR游戏开发02 | 性能优化设置
  • 不小心删除丢失了所有短信?如何在 iPhone 上查找和恢复误删除的短信
  • vue实现评论滚动效果
  • 网络编程day02(字节序、TCP编程)
  • 600 条最强 Linux 命令总结
  • 都2024年了还不明白Redis持久化?RDB文件、AOF文件、AOF重写
  • 编码器有哪些?
  • sheng的学习笔记-AI-概率图,隐马尔可夫HMM,马尔可夫随机场MRF,条件随机场CRF
  • 如何理解有效值电流?电流的均方根值
  • 并网光伏发电系统对电网电能质量的影响
  • 微信支付开发避坑指南
  • uboot 常用命令汇总
  • 〔开发系列〕一次关于小程序开发的深度总结
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • CEF与代理
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • js 实现textarea输入字数提示
  • Laravel Telescope:优雅的应用调试工具
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • React中的“虫洞”——Context
  • Redis 中的布隆过滤器
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • Vue2.0 实现互斥
  • 反思总结然后整装待发
  • 关于Java中分层中遇到的一些问题
  • 回顾 Swift 多平台移植进度 #2
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 前端攻城师
  • 一个SAP顾问在美国的这些年
  •  一套莫尔斯电报听写、翻译系统
  • 扩展资源服务器解决oauth2 性能瓶颈
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ######## golang各章节终篇索引 ########
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (1)(1.13) SiK无线电高级配置(五)
  • (2022 CVPR) Unbiased Teacher v2
  • (C#)获取字符编码的类
  • (day18) leetcode 204.计数质数
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (回溯) LeetCode 77. 组合
  • (强烈推荐)移动端音视频从零到上手(上)
  • (亲测有效)推荐2024最新的免费漫画软件app,无广告,聚合全网资源!
  • (十五)使用Nexus创建Maven私服
  • (四)事件系统
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • .net core + vue 搭建前后端分离的框架
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .NET 反射 Reflect
  • .NET 给NuGet包添加Readme
  • .NET 回调、接口回调、 委托