目录
1.Freemarker
1.1.什么是Freemarker
1.2.Freemarker模板组成部分
1.3.优点
2.SpringBoot整合Freemarker
2.1.配置
2.2.数据类型
2.2.1.字符串
2.2.2.数值
2.2.3.布尔值
2.2.4.日期
2.3.常见指令
2.3.1.处理不存在的值
2.3.2.assign
2.3.3.if/elseif/else
2.3.4.list
2.3.5.include
1.Freemarker
1.1.什么是Freemarker
FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
模板编写为FreeMarker Template Language (FTL)。它是简单的,专用的语言, 不是 像PHP那样成熟的编程语言。 那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。

这种方式通常被称为MVC (模型 视图 控制器) 模式,对于动态网页来说,是一种特别流行的模式。 它帮助从开发人员(Java 程序员)中分离出网页设计师(HTML设计师)。设计师无需面对模板中的复杂逻辑, 在没有程序员来修改或重新编译代码时,也可以修改页面的样式。
而FreeMarker最初的设计,是被用来在MVC模式的Web开发框架中生成HTML页面的,它没有被绑定到 Servlet或HTML或任意Web相关的东西上。它也可以用于非Web应用环境中。
FreeMarker 是免费的, 基于Apache许可证2.0版本发布。
1.2.Freemarker模板组成部分
FreeMarker模板文件主要由如下4个部分组成:
-  文本:直接输出的部分 
-  注释:使用<#-- ... -->格式做注释,里面内容不会输出 
-  插值:即${...}或#{...}格式的部分,类似于占位符,将使用数据模型中的部分替代输出 
-  FTL指令:即FreeMarker指令,全称是:FreeMarker Template Language,和HTML标记类似,但名字前加#予以区分,不会输出 
FreeMarker与Web容器无关
FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP,故此FreeMarker不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java等各种文本文件。
在Java Web领域,FreeMarker是应用广泛的模板引擎,主要用于MVC中的view层,生成html展示数据给客户端,可以完全替代JSP。
总之,FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写,模板中没有业务逻辑,外部Java程序通过数据库操作等生成数据传入模板(template)中,然后输出页面。它能够生成各种文本:HTML、XML、RTF、Java源代码等等,而且不需要Servlet环境,并且可以从任何源载入模板,如本地文件、数据库等等。
1.3.优点
FreeMarker的诞生是为了取代JSP。虽然JSP功能强大,可以写Java代码实现复杂的逻辑处理,但是页面会有大量业务逻辑,不利于维护和阅读,更不利于前后台分工,容易破坏MVC结构,所以舍弃JSP,选择使用FreeMarker是大势所趋。当前很多企业使用FreeMarker取代JSP,FreeMarker有众多的优点,如下所示:
-  很好地分离表现层和业务逻辑 
JSP功能很强大,它可以在前台编写业务逻辑代码,但这也带来了一个很大的弊端——页面内容杂乱,可读性差,这将会大大增加后期的维护难度。而FreeMarker职责明确,功能专注,仅仅负责页面的展示,从而去掉了繁琐的逻辑代码。FreeMarker的原理就是:模板+数据模型=输出,模板只负责数据在页面中的表现,不涉及任何的逻辑代码,而所有的逻辑都是由数据模型来处理的。用户最终看到的输出是模板和数据模型合并后创建的。
-  提高开发效率 
众所周知,JSP在第一次执行的时候需要转换成Servlet类,之后的每次修改都要编译和转换。这样就造成了每次修改都需要等待编译的时间,效率低下。而FreeMarker模板技术并不存在编译和转换的问题,所以就不会存在上述问题。相比而言,使用FreeMarker可以提高一定的开发效率。
-  明确分工 
JSP页面前后端的代码写到了一起,耦合度很高,前端开发需要熟悉后台环境,需要去调试,而后台开发人员需要去做不熟悉的前端界面设计。对两者而言,交替性的工作需要花费一定的学习成本,效率低下。而使用FreeMarker后,前后端完全分离,大家各干各的,互不影响。
-  简单易用,功能强大 
FreeMarker支持JSP标签,宏定义比JSP Tag方便,同时内置了大量常用功能,比如html过滤,日期金额格式化等等。FreeMarker代码十分简洁,上手快,使用非常方便。
2.SpringBoot整合Freemarker
2.1.配置
配置pom.xml,引入依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency>
请修改application.yml或application.properties文件,添加以下配置:
spring: freemarker: # 设置模板后缀名 suffix: .ftl # 设置文档类型 content-type: text/html # 设置页面编码格式 charset: UTF-8 # 设置页面缓存 cache: false # 设置ftl文件路径 template-loader-path: classpath:/templates # 设置静态文件路径,js,css等 mvc: static-path-pattern: /static/**
最后,请选择resources/templates目录,右键 New -> Freemarker 新建模板文件(.ftl)。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Freemarker</title> </head> <body> <h1>Hello FreeMarker!!!</h1> </body> </html>
注:这里Freemarker选项需要到settings -> Editor -> File And Code Templates中进行配置。
创建IndexController,并配置跳转页面路径:
@Controller
public class IndexController {
    @RequestMapping("/")
    public String toIndex(){
        return "index";
    }
} 
 
2.2.数据类型
2.2.1.字符串
在文本中确定字符串值的方法是看双引号,比如: "some text",或单引号,比如: 'some text'。这两种形式是等同的。 如果文本自身包含用于字符引用的引号 ( " 或 ')或反斜杠时, 应该在它们的前面再加一个反斜杠;这就是转义。 转义允许直接在文本中输入任何字符, 也包括换行。
${"It's \"quoted\" and
this is a backslash: \\"} 
字符串类型处理:
| 方法 | 含义 | 
|---|---|
| ?substring(start,end) | 截取字符串(左闭右开) | 
| ?uncap_first | 首字母小写输出 | 
| ?cap_first | 首字母大写输出 | 
| ?lower_case | 字母转小写输出 | 
| ?upper_case | 字母转大写输出 | 
| ?length | 获取字符串长度 | 
| ?starts_with("xx")?string | 是否以指定字符开头(boolean类型) | 
| ?ends_with("xx")?string | 是否以指定字符结尾(boolean类型) | 
| ?index_of("xx") | 获取指定字符的索引 | 
| ?trim | 去除字符串前后空格 | 
| ?replace("xx","xx") | 替换指定字符串 | 
字符串空值情况处理:
FreeMarker 的变量必须赋值,否则就会抛出异常。而对于 FreeMarker 来说,null 值和不存在的变量是完全一样的,因为 FreeMarker 无法理解 null 值。
<#-- 如果值不存在,直接输出会报错 -->
<#--${str}-->
<#-- 使用!,当值不存在时,默认显示空字符串 -->
${str!}<br>
<#-- 使用!"xx",当值不存在时,默认显示指定字符串 -->
${str!"这是一个默认值"}<br>
<#-- 使用??,判断字符串是否为空;返回布尔类型。如果想要输出,需要将布尔类型转换成字符串 -->
${(str??)?string}<br> 
 
2.2.2.数值
输入不带引号的数字就可以直接指定一个数字, 必须使用点作为小数的分隔符而不能是其他的分组分隔符。
${0.45}<br>
${18}<br>
<#-- 将数值转换成字符串输出 -->
${1000?c} <br>
<#-- 将数值转换成货币类型的字符串输出 -->
${1000?string.currency} <br>
<#-- 将数值转换成百分比类型的字符串输出 -->
${0.45?string.percent} <br>
<#-- 将浮点型数值保留指定小数位输出 (##表示保留两位小数) -->
${0.45723123?string["0.##"]} <br> 
 
2.2.3.布尔值
直接写 true 或者 false 就表示一个布尔值了,不需使用引号。
在freemarker中布尔类型不能直接输出;如果输出要先转成字符串
${flag?c}<br>
${flag?string}<br>
${flag?string("yes","no")}<br> 
 
2.2.4.日期
日期变量可以存储和日期/时间相关的数据。
在freemarker中日期类型不能直接输出;如果输出要先转成日期型或字符串
日期格式输出:
| 输出方式 | 说明 | 
|---|---|
| ?date | 年月日 | 
| ?time | 时分秒 | 
| ?datetime | 年月日时分秒 | 
| ?string("自定义格式") | 指定格式 | 
<#-- 输出日期格式 -->
${createDate?date} <br>
<#-- 输出时间格式 -->
${createDate?time} <br>
<#-- 输出日期时间格式 -->
${createDate?datetime} <br>
<#-- 输出格式化日期格式 -->
${createDate?string("yyyy年MM月dd日 HH时mm分ss秒")} <br>
 
 
2.3.常见指令
2.3.1.处理不存在的值
当试图访问一个不存在的变量时, FreeMarker 将会报错而导致模板执行中断。 通常我们可以使用两个特殊操作符来压制这个错误,控制这种错误情况。被控制的变量可以是顶层变量,哈希表或序列的子变量。 此外这些操作符还能处理方法调用的返回值不存在的情况。
-  默认值操作符 
使用形式: unsafe_expr!default_expr 或 unsafe_expr! or (unsafe_expr)!default_expr 或 (unsafe_expr)!
这个操作符允许你为可能不存在的变量指定一个默认值。
${message!"default Value."}
<#assign message="Zking">
${message!"default Value."}
 
输出结果如下:
default Value. Zking
如果默认值被省略了,那么结果将会是空串,空序列或空哈希表。(这是 FreeMarker 允许多类型值的体现)请注意,如果想让默认值为 0 或 false,则不能省略它。
(${message!})
<#assign message = "Zking">
(${message!})
 
 
-  不存在值检测操作符 
使用形式: unsafe_expr?? 或 (unsafe_expr)??
这个操作符告诉我们一个值是否存在。基于这种情况, 结果是
true或false。
<#if name??> 存在 <#else> 不存在 </#if>
-  exists用在逻辑判断 
exists用作逻辑判断,返回的是true或者false。
<#if name?exists>
    ${name}
</#if>
 
 
-  if_exists用来打印东西 
if_exists用于输出的时候,如果存在则输出,不存在就输出空字符串。
${name?if_exists}
 
 
2.3.2.assign
使用该指令你可以创建一个新的变量, 或者替换一个已经存在的变量。语法格式如下:
<#assign name1=value1 name2=value2 ... nameN=valueN> 或 <#assign name> capture this </#assign>
案例演示:
<#-- 创建一个str的变量 -->
<#assign str="hello">
<#-- 输出str -->
${str} <br>
<#-- 一次创建多个变量 -->
<#assign num=1 names=["zhangsan","lisi","wangwu"] >
${num} -- ${names?join(",")}
 
 
2.3.3.if/elseif/else
你可以使用 if, elseif 和 else 指令来条件判断是否越过模板的一个部分。 *condition* 必须计算成布尔值, 否则错误将会中止模板处理。elseif 和 else 必须出现在 if 内部 (也就是,在 if 的开始标签和结束标签之间)。 if 中可以包含任意数量的 elseif(包括0个) 而且结束时 else 是可选的。
<#if condition> ... <#elseif condition2> ... <#elseif condition3> ... ... <#else> ... </#if>
2.3.4.list
list 指令执行在 list 开始标签和 list 结束标签 ( list 中间的部分) 之间的代码, 对于在序列(或集合)中每个值指定为它的第一个参数。 对于每次迭代,循环变量将会存储当前项的值。
循环变量仅仅存在于 list 标签体内。 而且从循环中调用的宏/函数不会看到它(就像它只是局部变量一样)。
<#list sequence as item>
    Part repeated for each item
<#else>
    Part executed when there are 0 items
</#list>
 
在
list中的else仅从 FreeMarker 2.3.23 版本开始支持。
注意:
-  else部分是可选的, 而且仅仅从 FreeMarker 2.3.23 版本开始支持。
-  sequence: 将我们想要迭代的项,算作是序列或集合的表达式
-  item: 循环变量的名称 (不是表达式)
<#list arrs as item>
    ${item}
<#else>
    集合是空的
</#list>
 
 
2.3.5.include
可以使用它在你的模板中插入另外一个 FreeMarker 模板文件 (由 path 参数指定)
<#include path> 或 <#include path options>
这里:
-  path: 要包含文件的路径;
-  options: 一个或多个这样的选项:encoding=encoding,parse=parse-  encoding: 算作是字符串的表达式
-  parse: 算作是布尔值的表达式(为了向下兼容,也接受一部分字符串值)
-  ignore_missing: 算作是布尔值的表达式
 
-  
<h1>Hello Freemarker</h1> <#include "/common/head.ftl">



















