,先来一打小白兔;

3.1 总体结构

用程序语言编写的程序就是模板,模板也被成为FTL(代表FreeMarker模板语言)。

模板是由如下部分混合而成的:

  1. Text文本:文本会照着原样来输出;
  2. Interpolation插值:这部分的输出会被计算的值来代替。插值由${和}所分隔(或者#{和},这种风格已经不建议再使用了)。
  3. FTL tags标签:FTL标签和HTML标签很相似,但是它们却是给FreeMarker的指示,而且不会打印在输出内容中。
  4. Comments注释:FTL的注释和HTML的注释也很相似,但是它们是由<#–和–>来分隔的。注释会被FreeMarker所忽略,更不会在输出内容中显示。

FTL区分大小写;

FTL标签不可以在其他FTL标签和插值中使用,下面这样写是错的;

<#if <#include 'foo'>='bar'>...</#if>

注释可以放在FTL标签和插值中间;

3.2 指令

标签分为两种:

  • 开始标签:<#directivename parametes>

  • 结束标签:

指令有两种类型:预定义指令和用户自定义指令。对于用户自定义的指令使用@来代替#;

3.3 表达式

3.3.1 简介

${expression}

3.3.2 快速浏览(备忘单)

这里是给已经了解FreeMarker的人或有经验的程序员的一个提醒:

3.3.3 直接确定值
3.3.3.1 字符串

转义

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

输出:

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

转义序列表:

在1-4位的16进制码。下面这个示例中都是在字符串中放置版权符号“\xA9 1999-2001”,“\x0A9 1999-2001”,“\x00A9 1999-2001”;

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

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

将会打印:

${foo}
C:\foo\bar
实例

<ul>
<li>转义:${"It's \"quoted\" and this is a blackslash: \\"}</li>
<li>版权符号:${"\xA9 1999-2000"}</li>
<li>原生字符串:${r"${foo}"}</li>
</ul>

输出:

3.3.3.2 数字

科学记数法暂不支持使用(1E3就是错误的)。不能在小数点之前不写0(.5也是错误的);

3.3.3.3 布尔值

直接写true或false就表示一个布尔值了;

3.3.3.4 序列

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

<#list ["winter", "spring", "summer", "autumn"] as x>
${x}
</#list>

将会打印出:

winter
spring
summer
autumn

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

也可以用start..end定义存储数字范围的序列,这里start和end是处理数字值表达式,比如2..5和[2, 3, 4, 5]是相同的,但是使用前者会更有效率(内存占用少而且速度快)。可以看出前者也没有使用方括号,这样也可以用来定义递减的数字范围,比如5..2。(此外,还可以省略end,只需5..即可,到无穷大)。

实例

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/3/list.ftl


<#assign season=["summer", "winter", "spring", "autumn"]>
<p>
<#list season as s>
${s},
</#list>
</p>
<p>
<#list season[2..] as x>
${x},
</#list>
</p>

输出:

summer, winter, spring, autumn, 

spring, autumn, 
3.3.3.5 哈希表

键和值成对出现并以冒号分隔。{“name”:“green mouse”,“price”:150};

3.3.4 检索变量
3.3.4.1 顶层变量
3.3.4.2 从哈希表中检索数据

book.author.name来读取到auther的name;

如果我们想指定同一个表达式的子变量,那么还有另外一种语法格式:book[“title”]。

下面这些示例它们含义都是相等的:book.author.name, book["author"].name, book.author.["name"], book["author"]["name"]

当使用点式语法时,顶层变量名的命名也是相同的限制(命名时只能使用字母,数字,下划线,$,@等),而使用方括号语法形式时就没有这样的限制,它可以是任意的表达式。(为了FreeMarker支持XML,如果变量名是*(星号)或者**,那么就应该使用方括号语法格式)。

3.3.4.3 从序列中检索数据

animals[0].name

3.3.4.4 特殊变量

特殊变量是由FreeMarker引擎本身定义的,为了使用它们,可以按照如下语法形式来进行:.variable_name;

3.3.5 字符串操作
3.3.5.1 插值(或连接)
3.3.5.2 获取一个字符

user[0],假设user是”Big Joe“,那么

${user[0]}
${user[4]}

将会打印:

B
J

可以使用切分序列的方式来获取一定范围内的字符,比如user[1..4]{user[4..]},然而这种使用方法已经被废弃了,作为它的替代,可以使用内建函数substring。

实例

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/3/string.ftl


<ul>
<li>读取一个字符:${user[0]}</li>
<li>读取一定范围的字符:${user[1..5]}</li>
<li>这种操作已经废弃了,现在使用内建函数substring,${user?substring(1, 5)}</li>
</ul>

输出:

•读取一个字符:B
•读取一定范围的字符:ig Jo
•这种操作已经废弃了,现在使用内建函数substring,ig J
3.3.6 序列操作
3.3.6.1 连接

序列的连接可以使用+号来进行:

<#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
\- ${user}
</#list>

要注意不要在很多重复连接时使用序列连接操作,比如在循环中往序列上追加项目,通过这种方式进行的许多重复连接最终产生的序列读取的速度会变慢;

3.3.6.2 序列切分

使用[firstindex..lastindex]可以获取序列中的一部分,这里的firstindex和lastindex表达式的结果是数字,如果seq存储序列“a”,“b”,“c”,“d”,“f”,那么表达式seq[1..4]将会是含有“b”,“c”,“d”,“e”的序列。

实例

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/3/list.ftl


<h3>序列的操作</h3>
<ul>
<li>+连接:
<#list ["sumer", "winter"]+["spring", "autumn"] as x>
${x}.
</#list>
</li>
<li>序列切分:
<#list season[2..3] as x>
${x},
</#list>
</li>
</ul>
3.3.7 哈希表操作
3.3.7.1 连接

可以使用+号连接哈希表

<#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
3.3.8 算数运算

求模(求余): %

3.3.9 比较运算

测试两个值相等使用=(或者==,二者是完全等同的)

3.3.10 逻辑操作
3.3.11 内建函数

内建函数以?形式提供变量的不同形式或者其他信息。

例如得到字符串的大写形式:user?upper_case;

字符串使用的内建函数:

  • html:字符串中所有的特殊HTML字符都需要用实体引用来代替(比如<代替<)。

  • cap_first:字符串的第一个字母变为大写形式;
  • lower_case:字符串的小写形式;
  • upper_case:字符串的大写形式;
  • trim:去掉字符串首尾的空格;

序列使用的内建函数:

  • size:序列中的元素的个数

数字使用的内建函数:

  • int:数字的整数部分(比如-1.9?int就是-1)

示例:

${test?html}
${test?upper_case?html}

输出是:

Tom &amp; Jerry
TOM &amp; JERRY
3.3.12 方法调用

假设程序员定义了一个可供调用的方法repeat。第一个参数字符串类型,第二个参数是数值类型。

${repeat("What", 3)}

打印出:

WhatWhatWhat
3.3.13 处理不存在的值

要注意这个操作是FreeMarker2.3.7版本以后才有的(用来代替内建函数default,exists和if_exists);

3.3.13.1 默认值

unsafe_expr!default_expr或 unsafe_expr! 或 (unsafe_expr)!default_expr 或 (unsafe_expr)!

${mouse!"No mouse."}
<#assign mouse="Jerry">
${mouse!"No mouse."}

将会输出:

No mouse.
Jerry

默认值可以是任何类型的表达式,也可以不必是字符串。

hits!0;
colors!["red", "green", "blue"]

默认值表达式的复杂程序没有严格限制,你可以这么来写:

cargo.weight!(item.weight * itemCount+10)

如果默认值被忽略了,那么结果将会是空串,空序列或空哈希表。

(${mouse!})
<#assign mouse = "Jerry">
(${mouse!})

输出为:

()
(Jerry)

在不是顶层变量时,默认的操作符可以有两种方式:

product.color!"red"

当color不存在时(返回“red”)将会被处理,但是如果连product都不存在时将不会处理,也就是说这种写法product必须存在,否则模板就会报错。

(product.color)!"red"

这种写法,如果product不存在或者product存在而color不存在,都能显示默认值“red”而不会报错。

默认值操作也可以作用于序列,比如:

<#assign seq = ['a', 'b']>
${seq[0]!'-'}
${seq[1]!'-'}
${seq[2]!'-'}
${seq[3]!'-'}

输出为:

a
b
\-
\-
3.3.13.2 检测不存在的值

unsafe_expr??或者(unsafe_expr)??

<#if mouse??>
Mouse found
<#else>
No mouse found
</#if>
Creating mouse...
<#assign mouse = "Jerry">
<#if mouse??>
Mouse found
<#else>
No mouse found
</#if>

输出为:

No mouse found
Creating mouse...
Mouse found
3.3.14 括号
3.3.15 表达式中的空格

FTL忽略表达式中的多余空格。

3.3.16 操作符的优先级

3.4 插值

项目

  1. P1:https://github.com/yejq/FreeMarker-hello-java.git

  2. P2:https://github.com/yejq/FreeMarker-hello-web.git

FreeMarker笔记 第三章 模板的更多相关文章

  1. Android群英传笔记——第三章:Android控件架构与自定义控件讲解

    Android群英传笔记--第三章:Android控件架构与自定义控件讲解 真的很久没有更新博客了,三四天了吧,搬家干嘛的,心累,事件又很紧,抽时间把第三章大致的看完了,当然,我还是有一点View的基 ...

  2. spring boot 笔记--第三章

    spring boot 笔记 第三章,使用Spring boot 构建系统: 强烈建议支持依赖管理的构建系统,Maven或Gradle 依赖管理: Spring Boot的每版本都会提供它支持的依赖列 ...

  3. The Road to learn React书籍学习笔记(第三章)

    The Road to learn React书籍学习笔记(第三章) 代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() ...

  4. 《DOM Scripting》学习笔记-——第三章 DOM

    <Dom Scripting>学习笔记 第三章 DOM 本章内容: 1.节点的概念. 2.四个DOM方法:getElementById, getElementsByTagName, get ...

  5. 《Linux内核设计与分析》第六周读书笔记——第三章

    <Linux内核设计与实现>第六周读书笔记——第三章 20135301张忻估算学习时间:共2.5小时读书:2.0代码:0作业:0博客:0.5实际学习时间:共3.0小时读书:2.0代码:0作 ...

  6. [HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设

    [HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设 敲黑板!! <q>元素添加短引用,<blockquote>添加长引用 在段落里添加引用就使用< ...

  7. JVM学习笔记-第三章-垃圾收集器与内存分配策略

    JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...

  8. python学习笔记——第三章 串

    第三章 字符串学习 1.字符串不灵活, 它不能被分割符值 >>> format = "hello, %s. %s enough for ya?" >> ...

  9. C++ Primer 笔记 第三章

    C++ Primer 第三章 标准库类型 3.1using声明 例: using namespace atd; using std::cin; 3.2string类型 初始化方式 string s1 ...

随机推荐

  1. MatOfPoint作为minAreaRect的参数总是报错"throw new IllegalArgumentException("Incomatible Mat");

    MatOfPoint matPt = contours.get(i)       minRect.set(i, Imgproc.fitEllipse( new  MatOfPoint2f(matPt) ...

  2. Linux 添加环境变量和删除环境变量

    环境变量是一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息.例如PATH.在交叉编译中,会经常运用到环境变量的设置. 在linux中,查看当前全部的环境变量的命令式env. 当然也 ...

  3. GMT与UTC

    时间概念 — 24时区.GMT.UTC的意涵 许多人都知道两地时间表简称为GMT或UTC,而世界时区表则通称为World Time ,那么GMT与UTC的实质原意又是为何?世界时区又是怎么区分的?面盘 ...

  4. [POJ3264]Balanced Lineup(RMQ, ST算法)

    题目链接:http://poj.org/problem?id=3264 典型RMQ,这道题被我鞭尸了三遍也是醉了…这回用新学的st算法. st算法本身是一个区间dp,利用的性质就是相邻两个区间的最值的 ...

  5. 总结Selenium自动化测试方法(六)常见的异常错误处理

    六.常见的异常错误处理 NoSuchElementException: Message: Unable to locate element: {"method":"xpa ...

  6. HDU 1158 Employment Planning

    又一次看题解. 万事开头难,我想DP也是这样的. 呵呵,不过还是有进步的. 比如说我一开始也是打算用dp[i][j]表示第i个月份雇j个员工的最低花费,不过后面的思路就完全错了.. 不过这里还有个问题 ...

  7. 51nod1262 扔球

    相关讨论里的答案:(by mint_my ) 1.反弹n次,那起点S,每次反弹点,终点S共连接n+1条边,那么原问题变为从S走n+1条边回到S,为令n=n+12.设步长为a条边,gcd(a,n)==1 ...

  8. POJ 1847 Tram【Floyd】

    题意:给出n个站点,每个站点都有铁路通向其他站点 如果当前要走得路恰好是该站点的开关指向的铁路,则不用扳开关,否则要手动扳动开关,给出起点和终点,问最少需要扳动多少次开关 输入的第一行是n,start ...

  9. (六)6.11 Neurons Networks implements of self-taught learning

    在machine learning领域,更多的数据往往强于更优秀的算法,然而现实中的情况是一般人无法获取大量的已标注数据,这时候可以通过无监督方法获取大量的未标注数据,自学习( self-taught ...

  10. #define XXX do{...}while(0)

    <ol> <li>函数式宏定义的参数没有类型,预处理器只负责做形式上的替换,而不做参数类型检查,所以传参时要格外小心.</li> <li>调用真正函数的 ...