FreeMarker
概述
FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
HTML静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以使用FreeMarker将动态页面静态化。
工作原理
模板:就是一份已经写好了基本内容,有着固定格式的文档,其中空出或者用占位符标识的内容,由使用者来填充,不同的使用者给出的数据是不同的。在模板中的占位符,在模板运行时,由模板引擎来解析模板,并采用动态数据替换占位符部分的内容。
FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成Html,XML,JSP或Java 等文件。
优缺点
优点
FreeMarker不支持Java脚本代码;所以可以彻底的分离表现层和业务逻辑;
提高开发效率。开发过程中,界面设计和开发人员可以并行工作;不必等待完成页面原形后,再开发程序;
开发过程中的人员分工更加明确。使用FreeMarker后,作为界面开发人员,只专心创建HTML文件、图像以及Web页面的其他可视化方面,不用理会数据;而程序开发人员则专注于系统实现,负责为页面准备要显示的数据。
缺点
生成静态的HTML页面后,数据更新可能不及时;
需要学习FreeMarker模版语言。而且FreeMarker中的变量必须要赋值,如果不赋值,那么就会抛出异常。想避免错误就要应用if/elseif/else 指令进行判断,如果对每一个变量都判断的话,那么则反而增加了编程的麻烦。FreeMarker的map限定key必须是string,其他数据类型无法操作。
第一个FreeMarker例子
搭建maven项目
搭建java项目即可。FreeMarker的依赖坐标为:
1 2 3 4 5
| <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency>
|
pom.xml的内容为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <project xmlns=“http://maven.apache.org/POM/4.0.0″; xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”; xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd”;> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.taotao</groupId> <artifactId>taotao-parent</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>cn.itcast</groupId> <artifactId>itcast–freemarker</artifactId> <version>1.0.0-SNAPSHOT</version> <dependencies> <!– 单元测试 –> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> </dependency> </dependencies> </project>
|
控制台输出
文件输出
模版
详见《FreeMarker_Manual_zh_CN.pdf》的第26页。
基本语法
一些常见的符号说明:
${ }插值;只能输出数值、日期或者字符串,其它类型不能输出。
<#freemarker命令
<#– 注释 –>
<@使用自定义命令
??是判断对象是否存在
?函数调用
命令
自定义对象输出
模版文件内容:
控制
语法:
1 2 3 4 5 6 7 8 9 10
| <#if condition> … <#elseif condition2> … <#elseif condition3> … … <#else> … </#if>
|
这里:
condition , condition2 等:表达式将被计算成布尔值。
关键字:gt :比较运算符“大于”;gte :比较运算符“大于或等于”;lt :比较运算符“小于”;lte :比较运算符“小于或等于”
循环
语法:
1 2 3
| <#list sequence as item> … </#list>
|
这里:
sequence :表达式将被算作序列或集合
item :循环变量(不是表达式)的名称
模板中可以如下遍历:
变量
语法:<#assign name=value>
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <#– 定义字符变量 –> <#assign str=“Hello World.”> ${str} <hr> <#– 定义数值变量 –> <#assign num=123> ${num} <hr> <#– 定义布尔变量;但是${}只能输出数值或字符串,需要转换为字符串;?sring 的意思是调用boolean类型的内置函数string –> <#assign bool=true> ${bool?string} ${bool?string(“Yes”,“No”)} <hr> <#– 显示日期 .now 是当前时间 –> ${.now}—${.now?string(“yyyy年MM月dd日 HH:mm:ss”)} <hr> <#– 字符串转日期 –> <#assign dd =“2000-01-01”?date(“yyyy-MM-dd”)> ${dd?string(“yyyy年MM月dd日”)} <hr> <#– 获取范围字符 –> ${“我和黑马程序员的故事”[2..6]} 注:local一般使用在宏或函数里面。 Include
|
语法:<#include path>
说明:path 参数可以是如 “foo.ftl” 和 “../foo.ftl” 一样的相对路径,或者是如”/foo.ftl” 这样的绝对路径。
示例:
创建一个copyright.ftl文件;内容如下:
1 2 3 4 5 6 7 8
| Copyright 2000-2017 ${me}<br> All rights reserved. 再创建一个test_include.ftl文件,内容中引入copyright.ftl文件如下: <#assign me = “J.Liao”> <h1>Include test</h1> <p>wow… <hr> <#include “copyright.ftl”>
|
空值
在freemarker中对于空值必须手动处理。
在插值中处理空值:或者
${emp.name!} 表示name为空时什么都不显示
${emp.name!(“名字为空”)} 表示name为空时显示 名字为空
${(emp.company.name)!} 表示如果company对象为空则什么都不显示,!只用在最近的那个属性判断;所以如果遇上有自定义类型(导航)属性时,需要使用括号
${bool???string} 表示:首先??表示判断bool变量是否存在,存在返回true否则false,然后对返回的值调用其内置函数string
<#if str??> 表示去判断str变量是否存在,存在则true,不存在为false
模板示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <#– ${emp.name!}的使用 –> ${emp.name!} <hr> <#– ${emp.name!()}的使用 –> ${emp.name!(“名字为空。。。”)} —- 或者不加小括号也一样 —- ${emp.name!“名字为空。。。”} <hr> <#– ${bool???string}的使用 –> bool???string = ${bool???string} <hr> <#– ?? 判断一个变量是否存在,存在返回true,否则false –> <#assign str=“”> <#if str??> Str存在 <#else> str不存在 </#if>
|
列表与Map
列表
1 2 3 4 5 6 7 8 9 10 11
| <#assign nums = [1,2,3,4,5]> <#assign nums =6..10 > 全部输出: <#list nums as no> ${no} </#list> <br> 输出第1个到第4个: <#list nums[0..3] as no> ${no} </#list>
|
Map
Freemarker对于map的key而言,其key的类型必须为字符串。
处理map数据:
1 2 3 4 5
| <br> <#assign map = {“name”:“heima1”,“age”:10}> <#list map?keys as key> ${key}—-${map[“${key}”]} <br> </#list>
|
自定义命令macro
通过macro可以自定义命令,然后可以传递参数;在macro标签之间可以嵌套其它命令。另外;macro传递参数值时若参数有默认值则要把有默认值的参数放置在参数列表的最后。
<#– 第一个参数为命令的名称,是必须的;之后的为参数列表,可以添加多个 –>
自定义命令:
1 2 3 4 5 6 7 8 9 10 11 12
| <#macro sayHello name> Hello ${name} </#macro> <@sayHello name=“黑马”/> <hr> 自定义命令,多参数,默认参数: <#macro printNum name num=3> <#list 1..num as n> Hello ${name} — ${n}<br> </#list> </#macro> <@printNum name=“黑马”/>
|