FreeMarker设计指南(完整整理)

springBoot整合Freemark(模板引擎) 目录 一、Freemark介绍 1、freemark介绍 2、freemark构建 1、首先要构建一个freemark工程 2、导入pom依赖,更改资源文件 3、新建index界面 4、测试: 二、Freemark中booean、date类型 一、boolean类型: 1、c用法: 2、string用法: 3、then用法: 二、date类型: 三、空值处理: 1、第一种处理:默认值操作符 ​2、第二种处理:不存在值检测操作符 三、Freemark指令 ... 阅读详情

快速入门

(1)模板 + 数据模型 = 输出

FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念他们是分工劳动的:
设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;
程序员创建系统,生成设计页面要显示的数据。
经常会遇到的问题是:在Web页面(或其它类型的文档)中显示的信息在设计页面时是无效的,是基于动态数据的。在这里,你可以在HTML(或其它要输出的文本)中加入一些特定指令,FreeMarker会在输出页面给最终用户时,用适当的数据替代这些代码。

 

先来解释一下freemaker的基本语法了,
<# ... > 中存放所有freemaker的内容,之外的内容全部原样输出。
<@ ... /> 是函数调用
两个定界符内的内容中,第一个符号表示指令或者函数名,其后的跟随参数。freemaker提供的控制包括如下:
<#if condition><#elseif condition><#else> 条件判断
<#list hash_or_seq as var> 遍历hash表或者collection(freemaker称作sequence)的成员
<#macro name param1 param2 ... ><#nested param> 宏,无返回参数
<#function name param1 param2><#return val>函数,有返回参数
var?member_function(...) 用函数对var进行转换,freemaker称为build-ins。实际内部实现类似member_function(var, ...)
stringA[M .. N] 取子字符串,类似substring(stringA, M, N)
{key:value, key2:value2 ...} 直接定义一个hash表
[item0, item1, item2 ...] 直接定义一个序列
hash0[key0] 存取hash表中key对应的元素
seq0[5] 存取序列指定下标的元素
<@function1 param0 param1 ... /> 调用函数function1
<@macro0 param0 param1 ; nest_param0 nest_param1 ...> nest_body <
/@macro> 调用宏,并处理宏的嵌套
<#assign var = value > 定义变量并初始化
<#local var = value> 在 macro 或者 function 中定义局部变量并初始化
<#global var = value > 定义全局变量并初始化
${var} 输出并替换为表达式的值
<#visit xmlnode> 调用macro匹配xmlnode本身及其子节点
<#recurse xmlnode> 调用macro匹配xmlnode的子节点

 

下面是一个例子:

<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
<p>Our latest product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>

这个例子是在简单的HTML中加入了一些由${…}包围的特定代码,这些特定代码是FreeMarker的指令,而包含FreeMarker的指令的文件就称为模板(Template)。
至于user、latestProduct.url和latestProduct.name来自于数据模型(data model)。
数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成。
模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型。

下面是一个可能的数据模型:

(root)
|
+- user = "Big Joe"
|
+- latestProduct
|
+- url = "products/greenmouse.html"
|
+- name = "green mouse"

数据模型类似于计算机的文件系统,latestProduct可以看作是目录。

2、数据模型

(1)基础

在快速入门中介绍了在模板中使用的三种基本对象类型:scalars、hashes 和sequences,其实还可以有其它更多的能力:

  • scalars:存储单值
  • hashes:充当其它对象的容器,每个都关联一个唯一的查询名字
  • sequences:充当其它对象的容器,按次序访问
  • 方法:通过传递的参数进行计算,以新对象返回结果
  • 用户自定义FTL标记:宏和变换器

通常每个变量只具有上述的一种能力,但一个变量可以具有多个上述能力,如下面的例子:

(root)
|
+- mouse = "Yerri"
|
+- age = 12
|
+- color = "brown">

mouse既是scalars又是hashes,将上面的数据模型合并到下面的模板:

${mouse}       <#-- use mouse as scalar -->
${mouse.age} <#-- use mouse as hash -->
${mouse.color} <#-- use mouse as hash -->

输出结果是:

Yerri
12
brown
(2)Scalar变量

Scalar变量存储单值,可以是:

  • 字符串:简单文本,在模板中使用引号(单引号或双引号)括起
  • 数字:在模板中直接使用数字值
  • 日期:存储日期/时间相关的数据,可以是日期、时间或日期-时间(Timestamp);通常情况,日期值由程序员加到数据模型中,设计者只需要显示它们
  • 布尔值:true或false,通常在<#if …>标记中使用
(3)hashes 、sequences和集合

有些变量不包含任何可显示的内容,而是作为容器包含其它变量,者有两种类型:

  • hashes:具有一个唯一的查询名字和它包含的每个变量相关联
  • sequences:使用数字和它包含的每个变量相关联,索引值从0开始

集合变量通常类似sequences,除非无法访问它的大小和不能使用索引来获得它的子变量;集合可以看作只能由<#list …>指令使用的受限sequences

(4)方法

方法变量通常是基于给出的参数计算值。

下面的例子假设程序员已经将方法变量avg放到数据模型中,用来计算数字平均值:

The average of 3 and 5 is: ${avg(3, 5)}
The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
The average of the price of python and elephant is:
${avg(animals.python.price, animals.elephant.price)}
(5)宏和变换器

宏和变换器变量是用户自定义指令(自定义FTL标记),会在后面讲述这些高级特性

(6)节点

节点变量表示为树型结构中的一个节点,通常在XML处理中使用,会在后面的专门章节中讲

3、模板

(1)整体结构

模板使用FTL(FreeMarker模板语言)编写,是下面各部分的一个组合:

  • 文本:直接输出
  • Interpolation:由${和},或#{和}来限定,计算值替代输出
  • FTL标记:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出
  • 注释:由<#--和-->限定,不会输出

下面是以一个具体模板例子:

<html>
<head>
<title>Welcome!</title>
</head>
<body>
<#-- Greet the user with his/her name -->
<h1>Welcome ${user}!</h1>
<p>We have these animals:
<ul>
<#list animals as being>
<li>${being.name} for ${being.price} Euros
</#list>
</ul>
</body>
</html>

注意事项:

  • FTL区分大小写,所以list是正确的FTL指令,而List不是;${name}和${NAME}是不同的
  • Interpolation只能在文本中使用
  • FTL标记不能位于另一个FTL标记内部,例如:
<#if <#include 'foo'>='bar'>...</if>
  • 注释可以位于FTL标记和Interpolation内部,如下面的例子:
<h1>Welcome ${user <#-- The name of user -->}!</h1>
<p>We have these animals:
<ul>
<#list <#-- some comment... --> animals as <#-- again... --> being>
...
  • 余的空白字符会在模板输出时移除
(2)指令

在FreeMarker中,使用FTL标记引用指令。有三种FTL标记,这和HTML标记是类似的:

  • 开始标记:<#directivename parameters>
  • 结束标记:</#directivename>
  • 空内容指令标记:<#directivename parameters/>

有两种类型的指令:预定义指令和用户定义指令。

用户定义指令要使用@替换#,如<@mydirective>...</@mydirective>(会在后面讲述)。

FTL标记不能够交叉,而应该正确的嵌套,如下面的代码是错误的:

<ul>
<#list animals as being>
<li>${being.name} for ${being.price} Euros
<#if use = "Big Joe">
(except for you)
</#list>
</#if> <#-- WRONG! -->
</ul>

如果使用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息。

FreeMarker会忽略FTL标记中的空白字符,如下面的例子:

<#list
animals as
being
>
${being.name} for ${being.price} Euros
</#list >

但是,<、</和指令之间不允许有空白字符。

(3)表达式

直接指定值

  • 字符串

使用单引号或双引号限定

如果包含特殊字符需要转义,如下面的例子:

${"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: /

下面是支持的转义序列:

转义序列含义
/"双引号(u0022)
/'单引号(u0027)
 反斜杠(u005C)
/n换行(u000A)
/rReturn (u000D)
/tTab (u0009)
/bBackspace (u0008)
/fForm feed (u000C)
/l<
/g>
/a&
/{{
/xCode4位16进制Unicode代码

有一类特殊的字符串称为raw字符串,被认为是纯文本,其中的/和{等不具有特殊含义,该类字符串在引号前面加r,下面是一个例子:

${r"${foo}"}

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

输出的结果是:

${foo}

C:/foo/bar
  • 数字

直接输入,不需要引号

精度数字使用“.”分隔,不能使用分组符号

目前版本不支持科学计数法,所以“1E3”是错误的

不能省略小数点前面的0,所以“.5”是错误的

数字8、+8、08和8.00都是相同的

  • 布尔值

true和false,不使用引号

  • 序列

由逗号分隔的子变量列表,由方括号限定,下面是一个例子:

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

输出的结果是:

winter
spring
summer
autumn

列表的项目是表达式,所以可以有下面的例子:

[2 + 2, [1, 2, 3, 4], "whatnot"]

可以使用数字范围定义数字序列,例如2..5等同于[2, 3, 4, 5],但是更有效率,注意数字范围没有方括号

可以定义反递增的数字范围,如5..2

  • 散列(hash)

由逗号分隔的键/值列表,由大括号限定,键和值之间用冒号分隔,下面是一个例子:

{"name":"green mouse", "price":150}

键和值都是表达式,但是键必须是字符串

获取变量

  • 顶层变量: ${variable},变量名只能是字母、数字、下划线、$、@和#的组合,且不能以数字开头
  • 从散列中获取数据

可以使用点语法或方括号语法,假设有下面的数据模型:

(root)
|
+- book
| |
| +- title = "Breeding green mouses"
| |
| +- author
| |
| +- name = "Julia Smith"
| |
| +- info = "Biologist, 1923-1985, Canada"
|
+- test = "title"

下面都是等价的:

book.author.name
book["author"].name
book.author.["name"]
book["author"]["name"]

使用点语法,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字是任意表达式的结果

  • 从序列获得数据:和散列的方括号语法语法一样,只是方括号中的表达式值必须是数字;注意:第一个项目的索引是0

序列片断:使用[startIndex..endIndex]语法,从序列中获得序列片断(也是序列);startIndex和endIndex是结果为数字的表达式

  • 特殊变量:FreeMarker内定义变量,使用.variablename语法访问

字符串操作

  • Interpolation(或连接操作)

可以使用${..}(或#{..})在文本部分插入表达式的值,例如:

${"Hello ${user}!"}

${"${user}${user}${user}${user}"}

可以使用+操作符获得同样的结果

${"Hello " + user + "!"}

${user + user + user + user}

${..}只能用于文本部分,下面的代码是错误的:

<#if ${isBig}>Wow!</#if>

<#if "${isBig}">Wow!</#if>

应该写成:

<#if isBig>Wow!</#if>
  • 子串

例子(假设user的值为“Big Joe”):

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

${user[1..4]}

结果是(注意第一个字符的索引是0):

BJ

ig J

序列操作

  • 连接操作:和字符串一样,使用+,下面是一个例子:
<#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
- ${user}
</#list>

输出结果是:

- Joe
- Fred
- Julia
- Kate

散列操作

  • 连接操作:和字符串一样,使用+,如果具有相同的key,右边的值替代左边的值,例如:
<#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
- Joe is ${ages.Joe}
- Fred is ${ages.Fred}
- Julia is ${ages.Julia}

输出结果是:

- Joe is 30
- Fred is 25
- Julia is 18

算术运算

  • +、-、×、/、%,下面是一个例子:
${x * x - 100}
${x / 2}
${12 % 10}

输出结果是(假设x为5):

-75
2.5
2

操作符两边必须是数字,因此下面的代码是错误的:

${3 * "5"} <#-- WRONG! -->

使用+操作符时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串,例如:

${3 + "5"}

输出结果是:

35

使用内建的int(后面讲述)获得整数部分,例如:

${(x/2)?int}
${1.1?int}
${1.999?int}
${-1.1?int}
${-1.999?int}

输出结果是(假设x为5):

2
1
1
-1
-1
  • 比较操作符

使用=(或==,完全相等)测试两个值是否相等,使用!= 测试两个值是否不相等

=和!=两边必须是相同类型的值,否则会产生错误,例如<#if 1 = "1">会引起错误

Freemarker是精确比较,所以对"x"、"x "和"X"是不相等的

对数字和日期可以使用<、<=、>和>=,但不能用于字符串

由于Freemarker会将>解释成FTL标记的结束字符,所以对于>和>=可以使用括号来避免这种情况,例如<#if (x > y)>

另一种替代的方法是,使用lt、lte、gt和gte来替代<、<=、>和>=

  • 逻辑操作符

&&(and)、||(or)、!(not),只能用于布尔值,否则会产生错误

例子:

<#if x < 12 && color = "green">
We have less than 12 things, and they are green.
</#if>
<#if !hot> <#-- here hot must be a boolean -->
It's not hot.
</#if>
  • 内建函数

内建函数的用法类似访问散列的子变量,只是使用“?”替代“.”,下面列出常用的一些函数

    • 字符串使用的:

html:对字符串进行HTML编码

cap_first:使字符串第一个字母大写

lower_case:将字符串转换成小写

upper_case:将字符串转换成大写

trim:去掉字符串前后的空白字符

    • 序列使用的:

size:获得序列中元素的数目

    • 数字使用的:

int:取得数字的整数部分(如-1.9?int的结果是-1)

例子(假设test保存字符串"Tom & Jerry"):

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

输出结果是:

Tom &amp; Jerry
TOM &amp; JERRY
  • 操作符优先顺序
操作符组操作符
后缀[subvarName] [subStringRange] . (methodParams)
一元+expr、-expr、!
内建?
乘法*、 / 、%
加法+、-
关系<、>、<=、>=(lt、lte、gt、gte)
相等==(=)、!=
逻辑and&&
逻辑or双竖线
数字范围..
(4)Interpolation

Interpolation有两种类型:

  1. 通用Interpolation:${expr}
  1. 数字Interpolation:#{expr}或#{expr; format}

注意:Interpolation只能用于文本部分

  • 通用Interpolation

插入字符串值:直接输出表达式结果

插入数字值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个例子:

<#setting number_format="currency"/>
<#assign answer=42/>
${answer}
${answer?string} <#-- the same as ${answer} -->
${answer?string.number}
${answer?string.currency}
${answer?string.percent}

输出结果是:

$42.00
$42.00
42
$42.00
4,200%

插入日期值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个使用格式模式的例子:

${lastUpdated?string("yyyy-MM-dd HH: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)

插入布尔值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个例子:

<#assign foo=true/>
${foo?string("yes", "no")}

输出结果是:

yes
  • 数字Interpolation的#{expr; format}形式可以用来格式化数字,format可以是:

mX:小数部分最小X位

MX:小数部分最大X位

例子:

<#-- If the language is US English the output is: -->
<#assign x=2.582/>
<#assign y=4/>
#{x; M2} <#-- 2.58 -->
#{y; M2} <#-- 4 -->
#{x; m1} <#-- 2.6 -->
#{y; m1} <#-- 4.0 -->
#{x; m1M2} <#-- 2.58 -->
#{y; m1M2} <#-- 4.0 -->

4、杂项

(1)用户定义指令

宏和变换器变量是两种不同类型的用户定义指令,它们之间的区别是宏是在模板中使用macro指令定义,而变换器是在模板外由程序定义,这里只介绍宏

  • 基本用法

宏是和某个变量关联的模板片断,以便在模板中通过用户定义指令使用该变量,下面是一个例子:

<#macro greet>
<font size="+2">Hello Joe!</font>
</#macro>

作为用户定义指令使用宏变量时,使用@替代FTL标记中的#

<@greet></@greet>

如果没有体内容,也可以使用:

<@greet/>
  • 参数

在macro指令中可以在宏变量之后定义参数,如:

<#macro greet person>
<font size="+2">Hello ${person}!</font>
</#macro>

可以这样使用这个宏变量:

<@greet person="Fred"/> and <@greet person="Batman"/>

输出结果是:

<font size="+2">Hello Fred!</font>

and <font size="+2">Hello Batman!</font>

宏的参数是FTL表达式,所以下面的代码具有不同的意思:

<@greet person=Fred/>

这意味着将Fred变量的值传给person参数,该值不仅是字符串,还可以是其它类型,甚至是复杂的表达式

可以有多参数,下面是一个例子:

<#macro greet person color>
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>

可以这样使用该宏变量:

<@greet person="Fred" color="black"/>

其中参数的次序是无关的,因此下面是等价的:

<@greet color="black" person="Fred"/>

只能使用在macro指令中定义的参数,并且对所有参数赋值,所以下面的代码是错误的:

<@greet person="Fred" color="black" background="green"/>
<@greet person="Fred"/>

可以在定义参数时指定缺省值,如:

<#macro greet person color="black">
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>

这样<@greet person="Fred"/>就正确了

宏的参数是局部变量,只能在宏定义中有效

  • 嵌套内容

用户定义指令可以有嵌套内容,使用<#nested>指令执行指令开始和结束标记之间的模板片断

例子:

<#macro border>
<table border=4 cellspacing=0 cellpadding=4><tr><td>
<#nested>
</tr></td></table>
</#macro>

这样使用该宏变量:

<@border>The bordered text</@border>

输出结果:

<table border=4 cellspacing=0 cellpadding=4><tr><td>
The bordered text
</tr></td></table>

<#nested>指令可以被多次调用,例如:

<#macro do_thrice>
<#nested>
<#nested>
<#nested>
</#macro>
<@do_thrice>
Anything.
</@do_thrice>

输出结果:

Anything.
Anything.
Anything.

嵌套内容可以是有效的FTL,下面是一个有些复杂的例子: <@border> <ul> <@do_thrice> <li><@greet person="Joe"/> </@do_thrice> </ul> </@border> }}} 输出结果:

<table border=4 cellspacing=0 cellpadding=4><tr><td>
<ul>
<li><font size="+2">Hello Joe!</font>
<li><font size="+2">Hello Joe!</font>
<li><font size="+2">Hello Joe!</font>
</ul>
</tr></td></table>
宏定义中的局部变量对嵌套内容是不可见的,例如:
<#macro repeat count>
<#local y = "test">
<#list 1..count as x>
${y} ${count}/${x}: <#nested>
</#list>
</#macro>
<@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat>
输出结果:
test 3/1: ? ? ?
test 3/2: ? ? ?
test 3/3: ? ? ?
  • 在宏定义中使用循环变量

用户定义指令可以有循环变量,通常用于重复嵌套内容,基本用法是:作为nested指令的参数传递循环变量的实际值,而在调用用户定义指令时,在<@…>开始标记的参数后面指定循环变量的名字

例子:

<#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>
输出结果:
1. 0.5
2. 1
3. 1.5
4. 2 Last!

指定的循环变量的数目和用户定义指令开始标记指定的不同不会有问题

调用时少指定循环变量,则多指定的值不可见

调用时多指定循环变量,多余的循环变量不会被创建

(2)在模板中定义变量

在模板中定义的变量有三种类型:

  • plain变量:可以在模板的任何地方访问,包括使用include指令插入的模板,使用assign指令创建和替换
  • 局部变量:在宏定义体中有效,使用local指令创建和替换
  • 循环变量:只能存在于指令的嵌套内容,由指令(如list)自动创建

宏的参数是局部变量,而不是循环变量;局部变量隐藏(而不是覆盖)同名的plain变量;循环变量隐藏同名的局部变量和plain变量,下面是一个例子:

<#assign x = "plain">
1. ${x} <#-- we see the plain var. here -->
<@test/>
6. ${x} <#-- the value of plain var. was not changed -->
<#list ["loop"] as x>
7. ${x} <#-- now the loop var. hides the plain var. -->
<#assign x = "plain2"> <#-- replace the plain var, hiding does not mater here -->
8. ${x} <#-- it still hides the plain var. -->
</#list>
9. ${x} <#-- the new value of plain var. -->
<#macro test>
2. ${x} <#-- we still see the plain var. here -->
<#local x = "local">
3. ${x} <#-- now the local var. hides it -->
<#list ["loop"] as x>
4. ${x} <#-- now the loop var. hides the local var. -->
</#list>
5. ${x} <#-- now we see the local var. again -->
</#macro>
输出结果:
1. plain
2. plain
3. local
4. loop
5. local
6. plain
7. loop
8. loop
9. plain2

内部循环变量隐藏同名的外部循环变量,如:

<#list ["loop 1"] as x>
${x}
<#list ["loop 2"] as x>
${x}
<#list ["loop 3"] as x>
${x}
</#list>
${x}
</#list>
${x}
</#list>
输出结果:
loop 1
loop 2
loop 3
loop 2
loop 1
模板中的变量会隐藏(而不是覆盖)数据模型中同名变量,如果需要访问数据模型中的同名变量,使用特殊变量global,下面的例子假设数据模型中的user的值是Big Joe:
<#assign user = "Joe Hider">
${user} <#-- prints: Joe Hider -->
${.globals.user} <#-- prints: Big Joe -->
(3)名字空间

通常情况,只使用一个名字空间,称为主名字空间

为了创建可重用的宏、变换器或其它变量的集合(通常称库),必须使用多名字空间,其目的是防止同名冲突

  • 创建库

下面是一个创建库的例子(假设保存在lib/my_test.ftl中):

<#macro copyright date>
<p>Copyright (C) ${date} Julia Smith. All rights reserved.
<br>Email: ${mail}</p>
</#macro>
<#assign mail = "jsmith@acme.com">
使用import指令导入库到模板中,Freemarker会为导入的库创建新的名字空间,并可以通过import指令中指定的散列变量访问库中的变量:
<#import "/lib/my_test.ftl" as my>
<#assign mail="fred@acme.com">
<@my.copyright date="1999-2002"/>
${my.mail}
${mail}
输出结果:
<p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.
<br>Email: jsmith@acme.com</p>
jsmith@acme.com
fred@acme.com
可以看到例子中使用的两个同名变量并没有冲突,因为它们位于不同的名字空间

可以使用assign指令在导入的名字空间中创建或替代变量,下面是一个例子:

<#import "/lib/my_test.ftl" as my>
${my.mail}
<#assign mail="jsmith@other.com" in my>
${my.mail}
输出结果:
jsmith@acme.com
jsmith@other.com
数据模型中的变量任何地方都可见,也包括不同的名字空间,下面是修改的库:
<#macro copyright date>
<p>Copyright (C) ${date} ${user}. All rights reserved.</p>
</#macro>
<#assign mail = "${user}@acme.com">
假设数据模型中的user变量的值是Fred,则下面的代码:
<#import "/lib/my_test.ftl" as my>
<@my.copyright date="1999-2002"/>
${my.mail}
输出结果:
<p>Copyright (C) 1999-2002 Fred. All rights reserved.</p>
Fred@acme.com


补充(静态方法的调用):


方法1:
##定义配置文件 freemarkerstatic.properties
_Validator=com.longyou.util.Validator
_Functions=com.longyou.util.Functions
_EscapeUtils=com.longyou.util.EscapeUtils
/调用代码
${_Functions.toUpperCase("Hello")}<br>
${_EscapeUtils.escape("狼的原野")}

方法2:
${stack.findValue("@package.ClassName@method")}


补充:常用语法

EG.一个对象BOOK

1.输出 ${book.name}

空值判断:${book.name?if_exists },

${book.name?default(‘xxx’)}//默认值xxx

${ book.name!"xxx"}//默认值xxx

日期格式:${book.date?string('yyyy-MM-dd')}

数字格式:${book?string.number}--20

${book?string.currency}--<#-- $20.00 -->

${book?string.percent}—<#-- 20% -->

插入布尔值:

<#assign foo=ture />

${foo?string("yes","no")} <#-- yes -->

 

 

 

 

2.逻辑判断

a:

<#if condition>...

<#elseif condition2>...

<#elseif condition3>......

<#else>...

其中空值判断可以写成<#if book.name?? >

 

b:

<#switch value>

<#case refValue1>

...

<#break>

<#case refValue2>

...

<#break>

...

<#case refValueN>

...

<#break>

<#default>

...

 

3.循环读取

<#list sequence as item>

...

空值判断<#if bookList?size = 0>

e.g.

<#list employees as e>

${e_index}. ${e.name}

输出:

1. Readonly

2. Robbin


freemarker中Map的使用

<#list testMap?keys as testKey>
       < option value="${testKey}" >

              ${testMap[testKey]}
     </ option>
</#list>


freemarker的Eclipse插件

  • If you use Eclipse 2.x:
    1. Open the Window menu, then Open Perspective -> Install/Update
    2. Click with the right mouse button on the Feature Updates view, then select New -> Site Bookmark
    3. In the displayed dialog box, type "FreeMarker" for Name and "http://www.freemarker.org/eclipse/update" for URL. Leave the "Bookmark type" radio buttons on "Eclipse update site".
    4. Click Finish
    5. Open the tree node under the newly created update site named "FreeMarker", select the "FreeMarker X.Y.Z" feature, and install it using the Install now button in the preview pane.
  • If you use Eclipse 3.x:
    1. Help -> Software updates -> Find and install....
    2. Choose "Search for new features to install".
    3. Click Add Update Site..., and type "FreeMarker" for Name and "http://www.freemarker.org/eclipse/update" for URL.
    4. Check the box of the "FreeMarker" feature.
    5. "Next"-s until it is installed...
SpringBoot视图渲染技术全解析:Thymeleaf与FreeMarker实战指南 在Web应用开发中,视图渲染是将服务器端数据模型转换为客户端可呈现内容(如HTML、JSON)的核心过程,其原理基于模板引擎与数据模型的动态结合。这项技术对于构建动态页面、管理后台及服务端生成报表等场景具有重要价值,能显著提升开发效率与系统可维护性。SpringBoot作为主流Java框架,通过ViewResolver机制深度整合了多种视图技术,为不同应用场景提供了一站式解决方案。其中,Thymeleaf凭借其自然模板特性与Spring生态的深度集成,成为现代Web应用开发的首选;而FreeMarker则以 阅读详情

相关推荐

freeMark if嵌套

if的嵌套前段时间一直没有用过,用这个小例子看。能够很好理解 主要注意:这个括号

介绍freemaker的if语法

这些是FreeMarker模板引擎中的基本条件语句。在实际应用中,你可以根据需要组合这些语句来构建复杂的逻辑。条件可以是任何返回布尔值的表达式。例如,检查一个变量是否存在,或者比较两个值。FreeMarker还允许你使用逻辑运算符,如。语句用于基于条件的决策。如果条件为真,则执行。在FreeMarker中,还可以使用。FreeMarker的。进一步地,你可以使用。

m0_57236802的博客 7611

freeMark条件嵌套

【源码免费下载链接】:https://renmaiwang.cn/s/4s7qt FreeMarker 是一个强大的模板引擎,常用于Java Web开发中生成动态HTML、XML等文档。它允许开发者使用模板语言(如`<#if>`)来控制逻辑,与数据模型结合生成输出。在FreeMarker中,`<#if>`语句用于进行条件判断,如果表达式的值为真,则执行相应的代码块。在某些情况下,我们可能需要在`<#if>`语句内部再嵌套`<#if>`,这就是所谓的`if`嵌套。让我们理解`<#if>`的基本语法:```html<#if expression> <!-- 当expression为真时执行的代码 --></#if>```这里的`expression`可以是任何可以求值为布尔类型的FreeMarker表达式。例如,我们可以检查某个变量是否存在或其值是否非空:```html<#if user??> <p>Welcome, ${user.name}!</p></#if>```现在,进入`if`嵌套的话题。当我们需要在一个`<#if>`的条件满足后,再进行更复杂的判断时,就会用到嵌套:```html<#if user??> <#if user.isAdmin()> <p>You are an admin.</p> </#if> <#else> <p>You are not logged in.</p> </#if></#if>```在这个例子中,首先检查`user`是否存在。如果存在并且`user.isAdmin()`返回`true`,则显示“你是一个管理员”。如果`user`不存在,或者`user.isAdmin()`返回`false`,则显示“你没有登录”。在FreeMarker中,还可以使用`<#else>`来定义与`<#if>`相反的条件分支。如果`<#if>`的条件不成立,`

freemark(一): 简介及其使用

1. Freemark 简介 FreeMarker是一款模板引擎:一种基于魔板的、用来生成输出文本的通用工具。类似模板引擎还有Velocity,Common Template等。 对于java web开发来说,使用FreeMarker模板,可以将java代码从页面中分离出来。 开发人员只需关注业务逻辑代码,而由页面设计人员去设计显示效果, 两类人员各司其职,发挥其擅长的一面。 2. 常用指令 ...

开心的哈士奇 6126

OCC入门指南:从零开始掌握Open CASCADE Technology

本文是Open CASCADE Technology(OCC)的入门指南,详细介绍了这款开源C++三维几何建模内核的核心概念与价值。内容涵盖从零开始搭建开发环境、编写第一个显示立方体的程序,到深入理解其几何与拓扑核心、掌握Draw测试工具及Handle内存管理等关键编程范式,旨在帮助开发者快速掌握这一工业级CAD/CAE/CAM应用开发利器。

java5的博客 1275

智能座舱(七)——智能音频系统

本文剖析车载智能音频系统的核心技术,聚焦音响、功放、麦克风和广播收音机四大组件。音响系统通过多声道布局(如23扬声器阵列)结合动态声场校准算法,实现三维声场覆盖;功放系统采用高效D类技术,支持OTA音效调整和故障自愈;麦克风阵列运用波束成形技术实现精准拾音,并保障隐私安全;广播系统融合数字与网络技术提升音质。核心在于硬件标准化与算法差异化的协同,未来将朝集成化、AI个性化方向发展。

DC20160101的博客 1573

FreeMarker设计指南(完整整理)——转载自http://www.dlog.cn/wojiushicai/diary/11765

快速入门 (1)模板 + 数据模型 = 输出 FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念他们是分工劳动的:设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;程序员创建系统,生成设计页面要显示的数据。经常会遇到的问题是:在Web页面(或其它类型的文档)中显示的信息在设计页面时是无效的,是基于动态数据的。在这里,你可以在HTML(或其它要输出

446

uses ARM-Compiler ‘Default Compiler Version 5‘ which is not available. MDK5.37安装ARM_Compiler_5

MDK5.37安装ARM_Compiler_5 最后一个AC5编译器,从MDK5.37开始,不再默认安装,需要独立安装 ARMCompiler_506_Windows_x86_b960.zip (80.94MB) 否则使用AC5编译代码报错如下: Build started: Project: Project *** Target 'STM3210C_EVAL' uses ARM-Compiler 'Default Compiler Version 5' which is not available. *

mowwwcom的专栏 2万+

FreeMarker模板语言开发(整理版)

FreeMarker语言 FreeMarker语言概述 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。 FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序 虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据(如下图) ...

KamRoseLee的博客 2220

OpenClaw 生成测试用例

OpenClaw 只是躯干,Skills 才是灵魂。很多同学觉得 OpenClaw 没用,就像是买了一台顶级电脑却没装操作系统。通过这四步走,不仅可以学会如何让 AI 干活,更重要的是,可以学会如何管理 AI 的能力。

十二测试录 737

(建议收藏)2024最新 URL Scheme大全APP跳转界面地址更新中 ios快捷指令快捷方式链接跳转微信小程序必备autojs可用免root (可定制开发和提取URL Scheme 参数提取)

(建议收藏)2024最新 URL Scheme大全APP跳转界面地址更新中 ios快捷指令快捷方式链接跳转微信小程序必备autojs可用免root (可定制开发和提取URL Scheme 参数提取)

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1万+

FreeMarker 指南(一) -【纯属整理】

学习整理,如有侵权,请Email 告之 1、快速入门 (1)模板 + 数据模型 = 输出 l        FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念 l        他们是分工劳动的:设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;程序员创建系统,生成设计页面要显示的数据 l        经常会遇到的问题是:在Web页面(或

趙大叔 797

华为OD机试 - 服务中心选址(Python)

一个快递公司希望在一条街道建立新的服务中心。公司统计了该街道中所有区域在地图上的位置,并希望能够以此为依据为新的服务中心选址:使服务中心到所有区域的距离的总和最小。先输入区域数组positions的长度n(1 ≤ n ≤ 10^5)接下来 n 行每行输入成对的left和right值,以空格隔开。输出为location。

m0_46181452的博客 282

我与Freemarker二三事

最近工作不是很忙,所以想利用这段空闲时间学习学习。之前在微信上看到一篇关于FreeMarker的文章(点击这里查看),加之现在的项目中使用到了FreeMarker,当时为了急于完成在网上找了些速成的资料,所以我决定利用这段时间学习学习FreeMarker。阅读了官方文档,总结了一些自己觉得还挺有用的东西,整理在这里。

Earl_yuan的专栏 3356

在 SAP HANA 与 HANA Cloud 中,用 SQL DDL 创建数据库视图:从设计时工件到运行时对象的全链路实践

本文介绍了在SAP HANA中通过HDI容器使用DDL定义视图的方法。主要内容包括:1)采用.hdbview设计时工件存储视图定义,构建时自动转换为运行时视图,实现版本控制和权限隔离;2)开发前需准备HDI容器、MTA项目及配置.hdiconfig文件;3)详细说明.hdbview语法结构,重点讲解WITH READ ONLY和WITH STRUCTURED PRIVILEGE CHECK的使用场景;4)提供了从创建文件到构建验证的完整流程示例;5)强调跨容器访问时需通过.hdbgrants为#OO用户授予

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 275

使用LSTM进行多任务学习:共享模型预测多个目标

多任务学习是一种机器学习方法,旨在通过同时学习多个相关任务来提高模型的学习效率和泛化能力。MTL的核心思想是共享模型的参数,从而在不同任务之间捕捉到共享的特征。长短期记忆网络(LSTM)是循环神经网络(RNN)的一种改进版本,专门用于解决传统RNN在处理长序列时出现的梯度消失和梯度爆炸问题。LSTM通过引入多个门控机制(输入门、遗忘门和输出门)来控制信息的流动。本文详细探讨了如何使用LSTM进行多任务学习。我们介绍了多任务学习的理论基础、LSTM的特点,以及如何构建和训练一个多任务LSTM模型。

斌擎科技 1152

FreeMarker概述 - 纯属整理

学习整理,如有侵权,请Email 告之 |   FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写 l         FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序 l         虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面

趙大叔 543

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

FreeMarker教程_freemarker中border-bottom未生效(2)

user!body>

2401_85015326的博客 979

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

FlyCms主题定制教程:FreeMarker模板体系与个性化皮肤开发终极指南

FlyCms是一款基于Spring Boot+MyBatis+Solr+Ehcache架构的开源Java问答社区建站系统,内置了问答、文章、分享、话题等完整业务模块,而其**FlyCms主题定制**能力正是让无数站长打造个性化知识社区的关键。本文将从零开始,带你彻底搞懂FlyCms的FreeMarker模板体系,手把手完成**FlyCms皮肤开发**的完整流程,即使完全没有前端二次开发经验的新手,

gitblog_01055的博客 281

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

上一篇: SSI使用详解
下一篇: ajax 之 dwr 学习
BinTime
博客等级 码龄20年 29粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值