概念
FreeMarker 是一款 模板引擎 :
即一种基于模板和要改变的数据,并用来生成输出文本 ( HTML
网页,电子邮件,配置文件,源代码等) 的通用工具,是一个 Java
类库。
FreeMarker 被设计用来生成 HTML Web 页面,特别是基于
MVC
模式的应用程序,将视图从业务逻辑中抽离处理,业务中不再包括视图的展示,而是将视图交给
FreeMarker 来输出。虽然 FreeMarker 具有一些编程的能力,但通常由 Java
程序准备要显示的数据,由 FreeMarker
生成页面,通过模板显示准备的数据(如下图):
image-20230523232142086
FreeMarker 不是一个 Web 应用框架,而适合作为 Web
应用框架一个组件
FreeMarker 与容器无关,因为它并不知道 HTTP 或 Servlet。FreeMarker
同样可以应用于非 Web 应用程序环境。
FreeMarker 更适合作为 Model2 框架 (如 Struts
)的视图组件,你也可以在模板中使用 JSP 标记库
更多信息参考 英文官网
或者 中文官网
特性
1、通用目标
- 能够生成各种文本:HTML、XML、RTF、Java 源代码等等
- 易于嵌入到你的产品中:轻量级;不需要Servlet 环境
- 插件式模板载入器:可以从任何源载入模板,如本地文件、数据库等等
- 你可以按你所需生成文本:保存到本地文件;作为 Emal 发送;从Web
应用程序发送它返回给 Web 浏览器
2、强大的模板语言
- 所有常用的指令:include、if/elseif/else、循环结构
- 在模板中创建和改变变量
- 几乎在任何地方都可以使用复杂表达式来指定值
- 命名的宏,可以具有位置参数和嵌套内容
- 名字空间有助于建立和维护可重用的宏库,或将大工程分成模块,而不必担心名字冲突
- 输出转换块:在嵌套模板片段生成输出时,转换HTML转义、压缩、语法高亮等等,你可以定义自己的转换
3、通用数据模型
- FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在模板中显示
- 你可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等等)告诉模板开发者使用方法,使七不受技术细节的打扰
4、为Web准备
在模板语言中内建处理典型Web相关任务(如HTML转义)的结构
能够集成到Model2 Web应用框架中作为JSP的替代
支持]SP标记库
为MVC模式设计:分离可视化设计和应用程序逻辑;分离页面设计员和程序员
5、智能的国际化和本地化
字符集智能化(内部使用UNICODE)
数字格式本地化敏感
日期和时间格式本地化敏感
非US字符集可以用作标识(如变量名)
多种不同语言的相同模板
6、强大的XML的处理能力
- <#recurse>和<#visit>指令(2.3版本)用于递归遍历XML树。在模板中清楚和直接的访问XML对象模型开源论坛JForum就是使用了
FreeMarker 做为页面模板。
环境搭建
1、新建Maven Web项目

2、配置坐标依赖和部署插件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <dependencies> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> </dependency> </dependencies>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <bui1d> <finaTName>freemarker</finalName>
<pTugins> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.2.1.v20140609</version> </plugin> </p1ugins> </bui1d>
|
3、配置坐标依赖和部署插件
在项目的webapp/WEB-INF目录下的web.xml文件中,添加freemarker 相关
servlet 配置
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
| <?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <servlet> <servlet-name>freemarker</servlet-name> <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class> <init-param> <param-name>TemplatePath</param-name> <param-value>/</param-value> </init-param> <init-param> <param-name>default_encoding</param-name> <param-value>UTF-8</param-value> </init-param> </servlet> <servlet-mapping> <servTet-name>freemarker</servlet-name> <url-pattern>*.ft1</url-pattern> </servTet-mapping> </web-app>
|
4、编写Servlet类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.xxxx.controllter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
@WebServlet("/f01") public class FreeMarker01 extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute("msg","Hello FreeMarker!"); request.getRequestDispatcher("template/f01.ftl").forward(request,response); } }
|
5、新建模板文件 ftl
在webapp目录下新建template文件夹,创建f01.ftl文件
image-20230523235846218
6、启动项目
点击 Add Configuation ---> "+ " ---> maven ----->
填写运行名称跟端口

7、访问项目
浏览器地址栏输入: http://localhost:8989/f01

补充
freemarker的语法
1、html所有的标签都适合
2、js与css的使用,与html中的语法一致
修改f01.ftl文件,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <#-- css的使用 --> <style> h2{ font-family: 楷体; } </style> <#-- 获取数据 --> <h2>$(msg}</h2> <#-- js的使用 --> <script> alert("freemarkert'); </script>
|
效果如下:
image-20230524001214364
数据类型
Freemarker 模板中的数据类型由如下几种:
- 布尔型 : 等价于 Java 的 Boolean
类型,不同的是不能直接输出,可转换为字符串输出
- 日期型 : 等价于 java 的 Date
类型,不同的是不能直接输出,需要转换成字符串再输出
- 数值型 : 等价于 java 中的 int,float,double
等数值类型 ,有三种显示形式: 数值型 (默认)、货币型、百分比型
- 字符型 : 等价于 java
中的字符串,有很多内置函数
- sequence 类型 : 等价于 java 中的数组,list,set
等集合类型
- hash类型 : 等价于 java 中的Map 类型
布尔类型
1、在 Servlet 中设置不布尔类型的数据
1 2
| request.setAttribute("flag",true);
|
2、获取数据
在 freemarker 中布尔类型不能直接输出;如果输出要先转成字符串 方式一:
?c 方式二: ?string 或 ?string("true时的文本","false时的文本")
1 2 3
| ${flag?c} <br> ${flag?string} <br> $[flag?string("yes","no")} <br>
|
3、访问 url: http://localhost:8989/f01
,响应结果如下:
补充
可以配合 then 使用, then从 FreeMarker 2.3.23 版本开始存在
1 2
| <#assign foo = true> ${foo ? fhen('Y','N')}
|
结果
日期类型
1、在 Servlet 中设置日期类型的数据
1 2
| request.setAttribute("createDate",new Date0));
|
2、获得数据
日期类型
在freemarker中日期类型不能直接输出;如果输出要先转成日期型或字符串
1、年月日 ?date 2、时分秒 ?time 3、年月日时分秒 ?datetime 4、指定格式
?string (自定义格式,如: y:年 M:月 d:日 H:时 m:分 s:秒)
1 2 3 4 5 6 7 8
| <#-- 输出日期格式 --> ${createDate?date] <br> <#-- 输出时间格式--> ${createDate?time] <br> <#-- 输出日期时间格式 --> ${createDate?datetime] <br> <#-- 输出格式化日期格式 --> ${createDate?string("yyyy年MM月dd日 HH:mm:ss")} <br>
|
3、访问对应url,响应如下
1 2 3 4
| 2020-3-16 16:59:33 2020-3-16 16:59:33 2020/03/16 16:59:33
|
数值类型
1、在Servlet设置数值型的数据
1 2 3 4
| request.setAttribute("age",18); request.setAttribute("salary",10000); request.setAttribute("avg",0.545);
|
2、获取数据
数值类型
1、转字符串 普通字符串 ?c 货币型字符串 ?string.currency
百分比型字符串 ?string.percent
2、保留浮点型数值指定小数位(#表示一个小数位)?string["0.##"]·
1 2 3 4 5 6 7 8 9 10 11
| <#-- 直接输出数值型 --> ${age} <br> ${salary} <br> <#-- 将数值转换成字符串输出 --> ${salary?c} <br> <#-- 将数值转换成货币类型的字符串输出 --> ${salary?string.currency} <br> <#-- 将数值转换成百分比类型的字符串输出 --> ${avg?string.percent} <br> <#-- 将浮点型数值保留指定小数位输出 (##表示保留两位小数) --> ${avg?string["0.##"]} <br>
|
输出结果
1 2 3 4 5 6
| 18 10,000 10000 ¥ 10,000.00 55% (四舍五入) 0.55 (四舍五入)
|
字符串类型
1、在 Servlet 中设置字符串类型的数据
1 2 3
| request.setAttribute("msg1","Hello "); request.setAttribute("msg2","freemarker");
|
2、获取数据
数据类型:字符串类型 在freemarker中字符串类型可以直接输出; 1.
截取字符串(左闭右开) ?substring(start,end) 2. 首字母小写输出
?uncap_first 3. 首字母大写输出 ?cap_first 4. 字母转小写输出 ?lower_case
5. 字母转大写输出 ?upper_case 6. 获取字符串长度 ?length 7.
是否以指定字符开头(boolean类型) ?starts_with("xx")?string 8.
是否以指定字符结尾(boolean类型) ?ends_with("xx")?string 9.
获取指定字符的索引 ?index_of("xx") 10. 去除字符串前后空格 ?trim 11.
替换指定字符串 ?replace("xx","xx")
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
| <#-- 直接输出 --> ${msg1} - ${msg2} <br> ${msg1?string} - ${msg2?string} <br> <#-- 1. 截取字符串(左闭右开) ?substring(start,end) --> ${msg2?substring(1,4)} <br> <#-- 2. 首字母小写输出 ?uncap_first --> ${msg1?uncap_first} <br> <#-- 3. 首字母大写输出 ?cap_first --> ${msg2?cap_first} <br> <#-- 4. 字母转小写输出 ?lower_case --> ${msg1?lower_case} <br> <#-- 5. 字母转大写输出 ?upper_case --> ${msg1?upper_case} <br> <#-- 6. 获取字符串长度 ?length --> ${msg1?length} <br> <#-- 7. 是否以指定字符开头(boolean类型) ?starts_with("xx")?string --> ${msg1?starts_with("H")?string} <br> <#-- 8. 是否以指定字符结尾(boolean类型) ?ends_with("xx")?string --> ${msg1?ends_with("h")?string} <br> <#-- 9. 获取指定字符的索引 ?index_of("xxx") --> ${msg1?index_of("e")} <br> <#-- 10. 去除字符串前后空格 ?trim --> ${msg1?trim?length} <br> <#-- 11. 替换指定字符串 ?replace("xx","xxx") --> ${msg1?replace("o","a")}<br>
|
结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| Hello - freemarker Hello - freemarker ree hello Freemarker hello HELLO 6 (包含空格) true false 1 5 Hella
|
3、字符串空值情况处理
FreeMarker 的变量必须赋值,否则就会抛出异常。而对于 FreeMarker
来说,null 值和不存在的变量是完全一样的,因为 FreeMarker 无法理解 null
值。 FreeMarker 提供两个运算符来避免空值: ① ! :指定缺失变量的默认值
\({value!}:如果value值为空,则默认值是空字符串\){value!“默认值”}:如果value值为空,则默认值是字符串"默认值"
② ?? :判断变量是否存在 如果变量存在,返回 true,否则返回 false
${(value??)?string}
1 2 3 4 5 6 7 8
| <#-- 如果值不存在,直接输出会报错 --> <#--${str}--> <#-- 使用!,当值不存在时,默认显示空字符串 --> ${str!}<br> <#-- 使用!"xx",当值不存在时,默认显示指定字符串 --> ${str!"这是一个默认值"}<br> <#-- 使用??,判断字符串是否为空;返回布尔类型。如果想要输出,需要将布尔类型转换成字符串 --> ${(str??)?string}<br>
|
结果
sequence 类型
1、在Servlet中设置序列类型的数据
常见指令
页面静态化
运算符