您的位置:首页 > 其它

Freemarker notes | Freemarker学习笔记

2017-11-27 16:05 567 查看

Freemarker

应用场景



对比 JSP Freemarker Velocity

在java领域,表现层技术主要有三种:jsp、freemarker、velocity。

JSP

jsp是大家最熟悉的技术

优点:

1、功能强大,可以写java代码

2、支持jsp标签(jsp tag)

3、支持表达式语言(el)

4、官方标准,用户群广,丰富的第三方jsp标签库

5、性能良好。jsp编译成class文件执行,有很好的性能表现

缺点:

jsp没有明显缺点,非要挑点骨头那就是,由于可以编写java代码,如使用不当容易破坏mvc结构

Velocity

velocity是较早出现的用于代替jsp的模板语言

优点:

1、不能编写java代码,可以实现严格的mvc分离

2、性能良好,据说比jsp性能还要好些

3、使用表达式语言,据说jsp的表达式语言就是学velocity的

缺点:

1、不是官方标准

2、用户群体和第三方标签库没有jsp多。

3、对jsp标签支持不够好

freemarker

优点:

1、不能编写java代码,可以实现严格的mvc分离

2、性能非常不错

3、对jsp标签支持良好

4、内置大量常用功能,使用非常方便

5、宏定义(类似jsp标签)非常方便

6、使用表达式语言

缺点:

1、不是官方标准

2、用户群体和第三方标签库没有jsp多

选择freemarker的原因

1、性能。velocity应该是最好的,其次是jsp,普通的页面freemarker性能最差(虽然只是几毫秒到十几毫秒的差距)。但是在复杂页面上(包含大量判断、日期金额格式化)的页面上,freemarker的性能比使用tag和el的jsp好。

2、宏定义比jsp tag方便

3、内置大量常用功能。比如html过滤,日期金额格式化等等,使用非常方便

4、支持jsp标签

5、可以实现严格的mvc分离

6、jsp和freeMarker是两种不同的技术,或者说不通的理念。

jsp需要访问的时候访问Dao层抓取数据,生成html页面,返给浏览器。

freeMarker则是提前根据模板生成好html的静态页面,这样在访问时,直接访问到的就是一个静态页面,这个就是效率问题了,不过freeMarker适合用变化不大,但是内容很多的网页。

7. 相比较FreeMarker而言,Velocity更加简单、轻量级,但它的功能却没有FreeMarker那么强大。

FreeMarker Introduction

FreeMarker是一款模板引擎,是一个Java类库,用来生成html页面把页面静态化。

模板编写为FreeMarker Template Language(FTL)。

原理:模板页面=》解析标签和替换变量=》html页面

https://freemarker.apache.org/

2017-11-03 2.3.27

2016-06-26 2.3.25

2015-09-02 2.3.24-pre01 GNU=>Apache Incubation

http://fm-classic.sourceforge.net/

2004-06-15 2.2.8

2003-02-08 2.1.5

2002-06-12 2.0.3

1999-01-03 1.0

https://archive.apache.org/dist/incubator/freemarker/engine

Freemarker-2.3.25

Reference

Doc

https://freemarker.apache.org/docs/index.html

https://sourceforge.net/projects/freemarker/files/chinese-manual/

Java API

https://freemarker.apache.org/docs/api/index.html

https://freemarker.apache.org/docs/ref_directive_list.html

https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

FreeMarker模板开发指南

基本结构

插值:${...} interpolation(插值)。

标签:预定义标签以#开头;用户自定义的FTL标签使用@来代替#。

注释: <#-- -->。不像HTML注释<!-- -->那样,FTL注释不会出现在访问者的页面中。

Note:

Anything not an FTL tag or an interpolation or comment is considered static text and will not be interpreted by FreeMarker; it is just printed to the output as-is.

FTL是区分大小写的。

预定义指令可以不要 # , 不建议这样用。

可以在FTL标签和FTL注释中, 使用 [ 和 ] 来代替 < 和 >。

表达式

直接指定值

字符串
"Foo"
或者
'Foo'
或者
"It's \"quoted\""
或者
'It\'s "quoted"'
或者
r"C:\raw\string"


数字
123.45


布尔值
true
false


序列
["foo", "bar", 123.45]
; 值域:
0..9
,
0..<10
(或
0..!10
),
0..


哈希表
{"name":"green mouse", "price":150}


检索变量

顶层变量
user


从哈希表中检索数据
user.name
user["name"]


从序列中检索数据
products[5]


特殊变量
.main


字符串操作

插值(或连接)
"Hello ${user}!"
(或
"Hello " + user + "!"
)

获取一个字符
name[0]


字符串切分: 包含结尾:
name[0..4]
,不包含结尾:
name[0..<5]
,基于长度(宽容处理):
name[0..*5]
,去除开头:
name[5..]


序列操作

连接
users + ["guest"]


序列切分:包含结尾:
products[20..29]
, 不包含结尾:
products[20..<30]
,基于长度(宽容处理):
products[20..*10]
,去除开头:
products[20..]


哈希表操作

连接
passwords + { "joe": "secret42" }


算术运算
(x * 1.5 + 10) / 2 - y % 100


比较运算
x == y
x != y
x < y
x > y
x >= y
x <= y
x lt y
x lte y
x gt y
x gte y
, 等等。。。。。。

逻辑操作
!registered && (firstVisit || fromEurope)


内建函数
name?upper_case
,
path?ensure_starts_with('/')


方法调用
repeat("What", 3)


处理不存在的值

默认值
name!"unknown"
或者
(user.name)!"unknown"
或者
name!
或者
(user.name)!


检测不存在的值
name??
或者
(user.name)??


赋值操作
=
,
+=
,
-=
,
*=
,
/=
,
%=
,
++
,
--


Note:

原生字符串:在原生字符串中, 反斜杠和 ${ 没有特殊含义, 它们被视为普通的字符。在开始的引号或单引号之前放置字母r,${r"C:\foo\bar"}

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

值域表达式:start..end,start..<end, start..!end, start..*length, start..

变量

子变量

用.(点)来访问

空变量

FreeMarker不能引用不存在的变量,

一个不存在的变量和一个是null值的变量,对于FreeMarker来说是一样的。

可以指定一个默认值来避免变量丢失,在变量名后面跟着一个 !(感叹号)和默认值: ${user!"visitor"}

可以在变量名后面通过放置??来询问一个变量是否存在

<#if user??>

<h1>Welcome ${user}!</h1>

</#if>

多级访问的变量

animals.python.price!0 vs. (animals.python.price)!0

命名空间

通常来说,变量因为名称冲突时也会相互冲突。 所以要为每个库中的变量使用不同的命名空间。

简单的情况下可以只使用一个命名空间,称之为 主命名空间

import vs. include: <#import "/lib/my_test.ftl" as my>

Directives 指令|标签 介绍

if

<#if condition>

...

<#elseif condition2>

...

<#elseif condition3>

...

<#else>

...

</#if>

list, items, sep,else

<#list misc.fruits>

<p>Fruits:

<ul>

<#items as fruit>

<li>${fruit}<#sep> and</#sep>

</#items>

</ul>

<#else>

<p>We have no fruits.

</#list>

include可以在模板中插入另外一个FreeMarker模板文件

<#include "/copyright_footer.html">

数值类型

标量scalars:string, number, boolean, date|time

字符串只是字符的任意序列,不能将它用于计算目的,也不能和其它数字进行比较等等。

使用保留字 true 和 false 来指定布尔值。

受到Java平台的限制,FreeMarker 有时是不能决定日期的部哪分被使用。

FTL并没有独立的字符类型, 获取字符${user[0]}。

Containers: hash, sequence, collections

集合是有限制的序列。不能获取集合的大小, 也不能通过索引取出集合中的子变量,但是它们仍然可以通过
list
指令
来遍历。

序列(集合)中的变量可以是任意类型的, 这些变量也可以是哈希表,序列(或集合)。

Built-ins 内建函数|方法

在数值上添加

animal.name?cap_first

常见函数

user?html给出user的HTML转义版本,比如&会由&来代替。

user?upper_case给出user值的大写版本(比如“JOHN DOE”来替代“John Doe”)

animal.name?cap_first给出animal.name的首字母大写版本(比如“Mouse”来替代“mouse”)

user?length给出user值中字符的数量(对于“John Doe”来说就是8)

animals?size给出animals序列中项目的个数

list内使用

<#list animals as animal>…</#list>

l animal?index给出了在animals中基于0开始的animal的索引值

l animal?counter也像index,但是给出的是基于1的索引值

l animal?item_parity基于当前计数的奇偶性,给出字符串“odd”或“even”。在给不同行着色时非常有用,比如在<td class="${animal?item_parity}Row">中。

带参数的内建函数

l string: animal.protected?string("Y", "N")基于animal.protected的布尔值来返回字符串“Y”或“N”。

l animal?item_cycle('lightRow','darkRow')是item_parity更为常用的变体形式。

l fruits?join(", ")通过连接所有项,将列表转换为字符串,在每个项之间插入参数分隔符(比如“orange,banana”)

l user?starts_with("J")根据user的首字母是否是“J”返回布尔值true或false。

内建函数应用可以链式操作

user?upper_case?html

Freemarker自定义标签Directives

自定义指令用 macro 指令来定义

<#macro name param1 param2 ... paramN>

...

<#nested loopvar1, loopvar2, ..., loopvarN>

...

<#return>

...

</#macro>

Java实现

public class UpperDirective implements TemplateDirectiveModel

Freemarker自定义函数Function

ftl定义:function, return

<#function name param1 param2 ... paramN>

...

<#return returnValue>

...

</#function>

Java实现

public class IndexOfMethod implements TemplateMethodModelEx

所有内建函数

字符串内建函数

字符串属性:length, index_of, last_index_of,

字符串替换: replace, trim, cap_first, uncap_first, capitalize, chop_linebreak, keep_after, keep_after_last, keep_before, keep_before_last, left_pad, right_pad, lower_case, remove_beginning, remove_ending, ensure_ends_with, ensure_starts_with,

字符串判断:contains, starts_with, ends_with, boolean, matches, groups

字符串转换:split, word_list, number, date, time, datetime, string, url, url_path, html, xhtml, xml, j_string, js_string, json_string, rtf,

通用标志:i, f, r, m, s, c

支持使用这些通用标志的内建函数:replace, split, matches, keep_after, keep_after_last, keep_before, keep_before_last, ensure_starts_with

数字内建函数

abs, string, round, floor, ceiling, c,is_infinite,is_nan,lower_abc, upper_abc,

日期内建函数

string, date, time, datetime, date_if_unknown, time_if_unknown, datetime_if_unknown, iso_...(iso_utc, iso_local, …)

${openingTime?string["yyyy-MM-dd hh:mm:ss a"]}

布尔值内建函数

then, c, string

三元运算符: booleanExp?then(whenTrue, whenFalse)

序列内建函数

size, seq_contains, seq_index_of, seq_last_index_of, sort, sort_by, join, chunk, first, last, reverse,

哈希表内建函数

keys, values

XML结点内建函数

ancestors, children, node_name, node_namespace, node_type, parent, root

循环变量内建函数

counter, has_next, index, is_even_item, is_first, is_last, is_odd_item, item_cycle, item_parity, item_parity_cap

这些内建函数只能用于list 和 items 指令 的循环变量 (也可以用于已经废弃的 foreach 指令)。

Type independent built-ins

switch

priority?switch(1, "low", 2, "medium", 3, "high"),或者是 true?switch(priority <= 1, "low", priority == 2, "medium", priority >= 3, "high")。

很少使用的和专家级的内建函数

has_content, is_...(is_sring, is_number, is_date_like, is_time, is_datetime, …), eval,

   byte, double, float, int, long, short

number_to_date, number_to_time, number_to_datetime

所有指令: <#xxx …>…</#xxx>, <#xxx…>,

l assign, global, local, setting

l import, include

l if, else, elseif

l list, else, items, sep, break

l switch, case, default, break

l attempt, recover

l visit, recurse, fallback: xml

l escape, noescape

l function, return

l macro, nested, return

l compress

l flush

l ftl

l noparse, stop

l nt, t, lt, rt

l User-defined directive (<@...>)

FTL 中的保留名称

true:布尔值"true"

false:布尔值"false"

gt:比较运算符"大于"

gte:比较运算符"大于或等于"

lt:比较运算符"小于"

lte:比较运算符"小于或等于"

as:由少数指令使用

in:由少数指令使用

using:由少数指令使用

程序开发指南

开发步骤

创建 Configuration 实例

创建数据模型

获取模板

合并模板和数据模型

Configuration

配置(configuration)就是 freemarker.template.Configuration 对象, 它存储了常用(全局,应用程序级)的设置,定义了想要在所有模板中可用的变量(称为共享变量)。

应用程序典型的用法是使用一个独立的共享 Configuration 实例。

Shared variables

Settings
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: