前言
FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具。简单比如来说,html作为只关心前台,无后台数据,而后台数据通过freemarker模板来定义数据,然后在html中取出数据
入门程序
不妨以一个hello world程序作为入门,然后在研究它
1.建立一个普通的java项目
2.引入freemarker.jar包
3.在项目目录下建立模板目录:templates
4.在templates目录下,建立一个xx.ftl文件,内容如下
hello,${msg}
5.然后建立一个测试类:
public static void main(String[] args) throws Exception {
//创建Freemarker配置实例
Configuration cfg = new Configuration();
cfg.setDirectoryForTemplateLoading(new File(“templates”));
//创建数据模型
Map root = new HashMap();
root.put(“msg”, “world”);
//加载模板文件
Template t1 = cfg.getTemplate(“a.ftl”);
//显示生成的数据,//将合并后的数据打印到控制台
Writer out = new OutputStreamWriter(System.out);
t1.process(root, out);
out.flush();
}
输出结果:
hello,world
if指令
不妨先看例子
测试类中添加如下语句
root.put(“random”, new Random().nextInt(100));
模板文件添加如下语句
if语句测试:
${msg}是<#if msg==”world”>is right</#if>
if else 语句测试:
<#if random gt 60>
及格!
<#else>
不及格!</#if>
if else if else语句测试:
<#if random gte 90>
优秀!
<#elseif random gte 80>
良好!
<#else>
一般!
</#if>
随机输出结果:
if语句测试:
>world是is right
if else 语句测试:
及格!
if else if else语句测试:
优秀!
其中运用了比较运算符
- =(或者==): 判断两个值是否相等;
- !=: 判断两个值是否不相等;
注: =和!=可以用作字符串、数值和日期的比较,但两边的数据类型必须相同。而且FreeMarker的比较是精确比较,不会忽略大小写及空格。 (或者gt): 大于
=(或者gte): 大于等于
- <(或者lt): 小于
- <=(或者lte): 小于等于
注: 上面这些比较运算符可以用于数字和日期,但不能用于字符串。大部分时候,使用gt比>有更好的效果,因为FreeMarker会把>解释成标签的结束字符。可以使用括号来避免这种情况,如:<#if (x>y)>。
list指令
首先添加一个address类
然后测试类中添加如下语句
List list = new ArrayList();
list.add(new Address(“中国”,”北京”));
list.add(new Address(“中国”,”上海”));
list.add(new Address(“美国”,”纽约”));
root.put(“lst”, list);
模板文件添加如下
测试list指令:
<#list lst as temp >
${temp.country}
</#list>
include指令
在templates目录下随便写一个文件,比如tt.txt,里面目前只有test字符
模板文件增加如下:
<#include “tt.txt” />
将增加tt.txt里面的文本内容到该模板文件中
macro指令
该指令为宏指令,相当于定义函数和参数
第一个为函数名,后面为参数可有可无
如:
<#macro tt>
hello
world
</#macro>
引用<@tt />
输出结果
hello
world
定义待参宏指令
输出结果为hello,world
nested指令
该指定是插入引入的内容到相应位置如:
输出结果为
before now after
命名空间
当运行 FTL 模板时,就会有使用 assign 和 macro 指令创建的变量的集合,当引用不同的模板,就需要使用import指令
比如创建如下b.ftl
数据类型
一、直接指定值
直接指定值可以是字符串、数值、布尔值、集合及Map对象。
字符串
直接指定字符串值使用单引号或双引号限定。字符串中可以使用转义字符”\”。如果字符串内有大量的特殊字符,则可以在引号的前面加上一个字母r,则字符串内的所有字符都将直接输出。数值
数值可以直接输入,不需要引号。FreeMarker不支持科学计数法。布尔值
直接使用true或false,不使用引号。集合
集合用中括号包括,集合元素之间用逗号分隔。
使用数字范围也可以表示一个数字集合,如1..5等同于集合[1, 2, 3, 4, 5];同样也可以用5..1来表示[5, 4, 3, 2, 1]。Map对象
Map对象使用花括号包括,Map中的key-value对之间用冒号分隔,多组key-value对之间用逗号分隔。
注意:Map对象的key和value都是表达式,但key必须是字符串
6.时间对象
如:root.put(“date1”, new Date());
输出:${date1?string(“yyyy-MM-dd HH:mm”)}
其中后面的为日期输出格式
- JAVABEAN的处理
Freemarker中对于javabean的处理跟EL表达式一致,类型可自动转化
二、输出变量值
FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性。
- 顶层变量
所谓顶层变量就是直接放在数据模型中的值。输出时直接用${variableName}即可
输出集合元素
可 以根据集合元素的索引来输出集合元素,索引用中括号包括。如: 输出[“1”, “2”, “3”]这个名为number的集合,可以用${number[0]}来输出第一个数字。FreeMarker还支持用number[1..2]来表示原 集合的子集合[“2”, “3”]。
输出Map元素
对于JavaBean实例,FreeMarker一样把它看作属性为key,属性值为value的Map对象。
输出Map对象时,可以使用点语法或中括号语法,如下面的几种写法的效果是一样的:book.author.name book.author["name"] book["author"].name book["author"]["name"]
字符串操作
- 字符串连接
直接使用+连接
截取子串
截取子串可以根据字符串的索引来进行,如果指定一个索引值,则取得字符串该索引处的字符;如果指定两个索引值,则截取两个索引中间的字符串子串。如:<#assign number="01234"> ${number[0]} <#-- 输出字符0 --> ${number[0..3]} <#-- 输出子串“0123” -->
内建函数
FreeMarker提供了一些内建函数来转换输出,可以在任何变量后紧跟?,?后紧跟内建函数,就可以通过内建函数来转换输出变量。
字符串相关常用的内建函数:
- html: 对字符串进行HTML编码;
- cap_first: 使字符串第一个字母大写;
- lower_case: 将字符串转成小写;
- upper_case: 将字符串转成大写;
集合相关常用的内建函数:
- size: 获得集合中元素的个数;
数字值相关常用的内建函数:
- int: 取得数字的整数部分。
举例:
root.put(“htm2”, “粗体“);
内建函数:
${htm2?html}
其它类型
集合连接操作
Map连接操作
算术运算符
比较运算符
逻辑运算符
空值处理运算符
数据类型常见示例
直接指定值
字符串 : “Foo”或 者’Foo’或”It’s \”quoted\””或r”C:\raw\string”
数字:123.45
布尔值:true, false
序列:[“foo”, “bar”, 123.45], 1..100
哈希表:{“name”:”green mouse”, “price”:150}
检索变量 顶层变量:user
从哈希表中检索数据:user.name, user[“name”]
从序列中检索:products[5]
特殊变量:.main
字符串操作
插值(或连接):”Hello ${user}!”(或”Free” + “Marker”)
获取一个字符:name[0]
序列操作
连接:users + [“guest”]
序列切分:products[10..19] 或 products[5..]
哈希表操作
连接:passwords + {“joe”:”secret42”}
算数运算: (x * 1.5 + 10) / 2 - y % 100
比 较 运 算 : x == y, x != y, x < y, x > y, x >= y, x <= y,
x < y, 等等
逻辑操作:!registered && (firstVisit || fromEurope)
内建函数:name?upper_case
方法调用:repeat(“What”, 3)
处理不存在的值
默认值:name!”unknown” 或者(user.name)!”unknown” 或者
name! 或者 (user.name)!
检测不存在的值:name?? 或者(user.name)??