1. 简介
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等。
网页静态化技术和缓存技术的共同点都是为了减轻数据库的访问压力,但是具体的应用场景不同,缓存比较适合小规模的数据,而网页静态化比较适合大规模且相对变化不太频繁的数据。另外网页静态化还有利于SEO。
另外我们如果将网页以纯静态化的形式展现,就可以使用Nginx这样的高性能的web服务器来部署。
2. 使用
2.1 依赖的引入
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
2.2 模板文件
2.2.1 模板文件中四种元素
1)文本,直接输出的部分
2)注释,即<#--...-->格式不会输出到生成的文件中
3)插值(Interpolation):即${..}部分,将使用数据模型中的部分替代输出
注意:插值表达式区别于angular的插值表达式,只有一个大括号
4)FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出。
模板文件后缀名一般为 .ftl
如下是一个简单的模板文件(不包括FTL指令)
<html>
<head>
<meta charset="utf-8">
<title>Freemarker入门小DEMO </title>
</head>
<body>
<#--我只是一个注释,我不会输出到生成的文件中 -->
<!-- 我一个html注释,我会输出到生成的文件中 -->
${name},你好。${message}
</body>
</html>
2.3 使用Freemarker的基本步骤
1)创建configuration对象
2)设置输出文件编码格式
3)设置模板文件所在的目录
4)获取模板文件对象
5)创建模型数据,可以是pojo可以是map集合,一般我们在开发中使用的是map来作为数据模型
6)创建输出流对象,参数为目标文件地址
7)执行模板文件的process方法,生成文件到磁盘
8)关闭流对象
使用上面的模板文件,做一个简单是demo案例,代码如下:
package com.bjc.demo;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;
public class FreemarkerTest {
public static void main(String[] args) throws Exception {
// 1. 创建一个page对象
Configuration configuration = new Configuration(Configuration.getVersion());
// 2. 设置输出文件编码
configuration.setDefaultEncoding("utf-8");
// 3. 设置模板文件所在的目录
configuration.setDirectoryForTemplateLoading(new File("D:\\pinyougou\\freemarkerDemo\\src\\main\\resources"));
// 4. 获取模板对象
Template template = configuration.getTemplate("test.ftl");
// 5. 创建数据模型
Map map = new HashMap();
map.put("name", "张三");
map.put("message", "欢迎登录,本次登录时间是:" + new Date());
// 6. 创建一个输出流对象,参数为目标文件地址
Writer out = new FileWriter("d:\\test.html");
// 7. 执行模板对象方法,生成文件到磁盘
template.process(map, out );
// 8. 关闭流对象
out.close();
}
}
生成的文件如图;
注意:在模板文件中的插值表达式的变量,要在数据模型中定义或者在模板文件中使用“缺失变量默认值运算符”,否则会报错。
例如:将map.put("message", "欢迎登录,本次登录时间是:" + new Date());注释掉,错误信息如下:
3. 常用FTL指令
3.1 assign指令
此指令用于在页面上定义一个变量
语法:<#assign 变量名 = 变量值>
3.1.1 定义简单类型
<#assign linkman="周先生">
联系人:${linkman}
3.1.2 定义对象类型
<#assign info={"mobile":"13301231212",'address':'北京市昌平区王府街'} >
电话:${info.mobile} 地址:${info.address}
3.2 include指令
此指令用于模板文件的嵌套
语法:<#include "文件名">
<!--引入头文件-->
<#include "head.ftl" >
3.3 if指令
条件处理指令
语法:
1)不带else:<#if 条件表达式> 内容 </#if>
<#if success>
登录成功!
</#if>
2)带else:<#if 条件表达式> 内容1 <#else> 内容2 </#if>
<#if success>
登录成功!
<#else>
登录失败!
</#if>
注意:
1. success是数据模型中已经定义好的Boolean值。例如:map.put("success", false);
2. 在if指令中,条件变量也可以写成如下两种形式
<#if success = true>
或者
<#if success == true>
3.4 list循环指令
循环列表指令。
语法:
<#list list集合 as 变量>
${变量.属性)
<#list>
例如:
<#list goodsList as goods>
${goods_index+1} 商品名称:${goods.name} 价格:${goods.price} <br/>
</#list>
运行效果:
注意:
1. 下标索引的获取用 ${变量_index}
2. 循环集合在前,变量在as后,不要搞错了。
4. 内建函数
4.1 语法格式
变量 ? 函数名称
4.2 常用的内建函数
4.2.1 size
内建函数size可以用于获取集合的大小
共 ${goodsList?size} 条记录
4.2.2 eval
内建函数eval可用于将json字符串转成json对象
<#assign text="{'name':'张三','age':12}" />
<#assign data = text ? eval />
${(text ? eval).name} <br/> ${data.age}
运行结果:
4.2.3 时间函数
在Freemarker中,提供了3个实用的日期内建函数当前日期(date)和当前时间(time)和当前日期+时间函数(datetime)
例如:在数据模型定义如下数据 map.put("today", new Date());
当前日期:${today?date} <br/>
当前时间:${today?time}<br/>
当前日期+时间:${today?datetime}
运行结果;
4.2.4 日期格式化函数
例如:
日期格式化: ${today?string("yyyy年MM月")}
如图:
4.2.5 数字转换为字符串函数c
在Freemarker中,如果是数字,那么在页面显示的时候,默认会到上分隔符
例如:
${point} <br/>
${point?c}
运行效果:
5. 运算符
5.1 空值处理运算符
如果你在模板中使用了变量但是在代码中没有对变量赋值,那么运行生成时会抛出异常。但是有些时候,有的变量确实是null,怎么解决这个问题呢?
5.1.1 判断某变量是否存在 ??
语法:变量??
如果该变量存在,返回true,否则返回false
例如:
<#if aaa??>
aaa变量存在
<#else>
aaa变量不存在
</#if>
5.1.2 缺失变量默认值 !
我们除了可以判断是否为空值,也可以使用!对null值做转换处理
语法:变量!默认值
例如:
${aaa!'-'}
这样,在代码中不对aaa变量赋值,也不会报错了,当aaa为null则返回!后边的内容
5.1.3 算数运算符
FreeMarker表达式中完全支持算术运算,FreeMarker支持的算术运算符包括:+, - , * , / , %
5.1.4 逻辑运算符
逻辑运算符有如下几个:
逻辑与:&&
逻辑或:||
逻辑非:!
逻辑运算符只能作用于布尔值,否则将产生错误
5.1.5 比较运算符
表达式中支持的比较运算符有如下几个:
1 =或者==:判断两个值是否相等.
2 !=:判断两个值是否不等.
3 >或者gt:判断左边值是否大于右边值
4 >=或者gte:判断左边值是否大于等于右边值
5 <或者lt:判断左边值是否小于右边值
6 <=或者lte:判断左边值是否小于等于右边值
注意:
1. =和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误
2. FreeMarker是精确比较,"x","x ","X"是不等的。
3. 其它的运行符可以作用于数字和日期,但不能作用于字符串。
4. 大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为 FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况。例如:
<#if (x>y)>