一、FreeMaker介绍

FreeMarker是一款免费的Java模板引擎,是一种基于模板和数据生成文本(HMLT、电子邮件、配置文件、源代码等)的工具,它不是面向最终用户的,而是一款程序员使用的组件。

FreeMarker最初设计是用来在MVC模式的Web开发中生成HTML页面的,所以没有绑定Servlet或任意Web相关的东西上,所以它可以运行在非Web应用环境中。

发展史

FreeMarker第一版在1999年未就发布了,2002年初使用JavaCC(Java Compiler Compiler是一个用Java开发的语法分析生成器)重写了FreeMarker的核心代码,2015年FreeMarker代码迁移到了Apache下。

GitHub地址:https://github.com/apache/freemarker

工作原理

FreeMarker模板存储在服务器上,当有用户访问的时候,FreeMarker会查询出相应的数据,替换模板中的标签,生成最终的HTML返回给用户,如下图:

二、FreeMarker基础使用

基础使用分为3部分,这3部分组成了FreeMarker:

  • 指令
  • 表达式

指令是FreeMarker用来识别转换的特殊标签,表达式是标签里具体的语法实现,其他部分是一些不好分类的模板。

2.1 指令

使用FTL(freemarker template language)标签来调用指令。

指令速览:

  • assign
  • attempt, recover
  • compress
  • escape, noescape
  • flush
  • ftl
  • function, return
  • global
  • if, else, elseif
  • import
  • include
  • list, else, items, sep, break
  • local
  • macro, nested, return
  • noparse
  • nt
  • setting
  • stop
  • switch, case, default, break
  • t, lt, rt
  • visit, recurse, fallback
  • 用户自定义标签

下来我们分别来看每个指令对应具体使用。

2.1.1 assign 代码声明

assign 分为变量和代码片段声明两种。

2.1.1.1 变量声明

可以是单变量声明,或多变量声明,下面是多变量声明的示例:

  1. <#assign name="adam" age=18 "sex"="man">
  2. ${name} - ${age} - ${"sex"}

单个变量的话,只写一个就可以了。

2.1.1.2 代码片段声明
  1. <#assign code>
  2. <#list ["java","golang"] as c>
  3. ${c}
  4. </#list>
  5. </#assign>
  6. ${code}

其中 ${code} 是用来执行方法的,如果不调用话,代码片段不会执行。

2.1.2 attempt, recover 异常指令

attempt(尝试), recover(恢复)指令类似于程序的try catch,示例如下:

  1. <#attempt>
  2. i am ${name}
  3. <#recover>
  4. error name
  5. </#attempt>

如果有变量“name”就会正常显示,显示“i am xxx”,如果没有变量就会显示“error name”。

2.1.3 compress 压缩代码移除空白行

  1. <#compress>
  2. 1 2 3 4 5
  3. test only
  4. I said, test only
  5. </#compress>
  6. 1 2 3 4 5
  7. test only
  8. I said, test only

效果如下:

对空白不敏感的格式,移除空白行还是挺有用的功能。

2.1.4 escape, noescape 转义,不转义

2.1.4.1 escape使用
  1. <#escape x as x?html>
  2. ${firstName}
  3. ${lastName}
  4. </#escape>

上面的代码,类似于:

  1. ${firstName?html}
  2. ${lastName?html}

Java代码:

  1. @RequestMapping("/")
  2. public ModelAndView index() {
  3. ModelAndView modelAndView = new ModelAndView("/index");
  4. modelAndView.addObject("firstName", "<span style='color:red'>firstName</span>");
  5. modelAndView.addObject("lastName", "lastName");
  6. return modelAndView;
  7. }

最终的效果是:

2.1.4.2 “?html”语法解析

单问号后面跟的是操作函数,类似于Java中的方法名,html属于内建函数的一个,表示字符串会按照HTML标记输出,字符替换规则如下:

  • < 替换为 &lt;
  • > 替换为 &gt;
  • & 替换为 &amp;
  • " 替换为 &quot;
2.1.4.3 noescape使用

HTML代码:

  1. <#escape x as x?html>
  2. <#noescape>
  3. ${firstName}
  4. </#noescape>
  5. ${lastName}
  6. </#escape>

Java代码:

  1. @RequestMapping("/")
  2. public ModelAndView index() {
  3. ModelAndView modelAndView = new ModelAndView("/index");
  4. modelAndView.addObject("firstName", "<span style='color:red'>firstName</span>");
  5. modelAndView.addObject("lastName", "lastName");
  6. return modelAndView;
  7. }

最终效果:

2.1.5 function, return 方法声明

代码格式:

  1. <#function name param1 param2 ... paramN>
  2. ...
  3. <#return returnValue>
  4. ...
  5. </#function>
  • name 为方法名称
  • param1, param2,paramN 方法传递过来的参数,可以有无限个参数,或者没有任何参数
  • return 方法返回的值,可以出现在function的任何位置和出现任意次数

示例代码如下:

  1. <#function sum x y z>
  2. <#return x+y+z>
  3. </#function>
  4. ${sum(5,5,5)}

注意:function如果没有return是没有意义的,相当于返回null,而function之中信息是不会打印到页面的,示例如下:

  1. <#function wantToPrint>
  2. 这里的信息是显示不了的
  3. </#function>
  4. <#if wantToPrint()??>
  5. Message:${wantToPrint()}
  6. </#if>

“??”用于判断值是否是null,如果为null是不执行的。如果不判null直接使用${}打印,会报模板错误,效果如下:

2.1.6 global 全局代码声明

语法如下:

  1. <#global name=value>

  2. <#global name1=value1 name2=value2 ... nameN=valueN>

  3. <#global name>
  4. capture this
  5. </#global>

global使用和assign用法类似,只不过global声明是全局的,所有的命名空间都是可见的。

2.1.7 if elseif else 条件判断

语法如下:

  1. <#if condition>
  2. ...
  3. <#elseif condition2>
  4. ...
  5. <#elseif condition3>
  6. ...
  7. ...
  8. <#else>
  9. ...
  10. </#if>

示例如下:

  1. <#assign x=1 >
  2. <#if x==1>
  3. x is 1
  4. <#elseif x==2>
  5. x is 2
  6. <#else>
  7. x is not 1
  8. </#if>

2.1.8 import 引入模板

语法: <#import path as hash>

示例如下

footer.ftl 代码如下:

  1. <html>
  2. <head>
  3. <title>王磊的博客</title>
  4. </head>
  5. <body>
  6. this is footer.ftl
  7. <#assign copy="来自 王磊的博客">
  8. </body>
  9. </html>

index.ftl 代码如下:

  1. <html>
  2. <head>
  3. <title>王磊的博客</title>
  4. </head>
  5. <body>
  6. <#import "footer.ftl" as footer>
  7. ${footer.copy}
  8. </body>
  9. </html>

最终输出内容:

  1. 来自 王磊的博客

2.1.9 include 嵌入模板

语法: <#include path>

示例如下

footer.ftl 代码如下:

  1. <html>
  2. <head>
  3. <title>王磊的博客</title>
  4. </head>
  5. <body>
  6. this is footer.ftl
  7. <#assign copy="来自 王磊的博客">
  8. </body>
  9. </html>

index.ftl 代码如下:

  1. <html>
  2. <head>
  3. <title>王磊的博客</title>
  4. </head>
  5. <body>
  6. <#include "footer.ftl">
  7. </body>
  8. </html>

最终内容如下:

  1. this is footer.ftl

2.1.10 list, else, items, sep, break 循环

2.1.10.1 正常循环

输出1-3的数字,如果等于2跳出循环,代码如下:

  1. <#list 1..3 as n>
  2. ${n}
  3. <#if n==2>
  4. <#break>
  5. </#if>
  6. </#list>

注意:“1..3”等于[1,2,3]。

结果: 1 2

2.1.10.2 使用items输出

示例如下:

  1. <#list 1..3>
  2. <ul>
  3. <#items as n>
  4. <li>${n}</li>
  5. </#items>
  6. </ul>
  7. </#list>
2.1.10.3 sep 使用

跳过最后一项

  1. <#list 1..3 as n>
  2. ${n}
  3. <#sep>,</#sep>
  4. </#list>

最终结果:1 , 2 , 3

2.1.10.4 数组最后一项

代码如下:

  1. <#list 1..3 as n>
  2. ${n}
  3. <#if !n_has_next>
  4. 最后一项
  5. </#if>
  6. </#list>

使用“变量_has_next”判断是否还有下一个选项,来找到最后一项,最终的结果:1 2 3 最后一项

2.1.11 macro 宏

宏:是一个变量名的代码片段,例如:

  1. <#macro sayhi name>
  2. Hello, ${name}
  3. </#macro>
  4. <@sayhi "Adam" />

相当于声明了一个名称为“sayhi”有一个参数“name”的宏,使用自定义标签“@”调用宏。

输出的结果: Hello, Adam

2.1.12 switch, case, defalut, break 多条件判断

示例代码如下:

  1. <#assign animal="dog" >
  2. <#switch animal>
  3. <#case "pig">
  4. This is pig
  5. <#break>
  6. <#case "dog">
  7. This is dog
  8. <#break>
  9. <#default>
  10. This is Aaimal
  11. </#switch>

2.1.13 扩展知识

指令自动忽略空格特性

FreeMarker会忽略FTL标签中的空白标记,所以可以直接写:

  1. <#list ["老王","老李","老张"]
  2. as
  3. p>
  4. ${p}
  5. </#list>

即使是这个格式也是没有任何问题的,FreeMarker会正常解析。

2.2 表达式

2.2.1 字符串拼接

字符拼接代码:

  1. <#assign name="ABCDEFG">
  2. ${"Hello, ${name}"}

结果:Hello, ABCDEFG

2.2.2 算术运算

2.2.2.1 算术符

算术符有五种:

  • +
  • -
  • *
  • /
  • % 求余(求模)

示例代码:

  1. ${100 - 10 * 20}

输出:

  1. -100
2.2.2.2 数值转换
  1. ${1.999?int}

输出:

  1. 1

注意:数值转换不会进行四舍五入,会舍弃小数点之后的。

2.2.3 内建函数(重点)

内建函数:相当于我们Java类里面的内置方法,非常常用,常用的内建函数有:时间内建函数、字符内建函数、数字内建函数等。

2.2.3.1 单个问号和两个问号的使用和区别

单问号:在FreeMarker中用单个问号,来调用内建函数,比如: ${"admin"?length} 查看字符串“admin”的字符长度,其中length就是字符串的内建函数。

双引号:表示用于判断值是否为null,比如:

  1. <#if admin??>
  2. Admin is not null
  3. </#if>
2.2.3.2 字符串内建函数
2.2.3.2.1 是否包含判断

使用contains判断,代码示例:

  1. <#if "admin"?contains("min")>
  2. min
  3. <#else >
  4. not min
  5. </#if>

输出:

  1. min
2.2.3.2.2 大小写转换

示例代码:

  1. <#assign name="Adam">
  2. ${name?uncap_first}
  3. ${name?upper_case}
  4. ${name?cap_first}
  5. ${name?lower_case}

输出:

  1. adam ADAM Adam adam

更多的字符串内建函数:https://freemarker.apache.org/docs/ref_builtins_string.html

2.2.3.3 数字内建函数

示例代码:

  1. ${1.23569?string.percent}
  2. ${1.23569?string["0.##"]}
  3. ${1.23569?string["0.###"]}

输出:

  1. 124% 1.24 1.236

注意:

  • 使用string.percent计算百分比,会自动四舍五入。
  • 使用“?string["0.##"]”可以自定义取小数点后几位,会自动四舍五入。
2.2.3.4 时间内建函数
2.2.3.4.1 时间戳转换为任何时间格式

代码:

  1. <#assign timestamp=1534414202000>
  2. ${timestamp?number_to_datetime?string["yyyy/MM/dd HH:mm"]}

输出:

  1. 2018/08/16 18:10
2.2.3.4.2 时间格式化

示例代码:

  1. <#assign nowTime = .now>
  2. ${nowTime} <br />
  3. ${nowTime?string["yyyy/MM/dd HH:mm"]} <br />

输出:

  1. 2018-8-16 18:33:50
  2. 2018/08/16 18:33

更多内建方法:https://freemarker.apache.org/docs/ref_builtins.html

三、Spring Boot 集成

3.1 集成环境

  • Spring Boot 2.0.4
  • FreeMaker 2.3.28
  • JDK 8
  • Windows 10
  • IDEA 2018.2.1

3.2 集成步骤

3.2.1 pom.xml 添加FreeMaker依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-freemarker</artifactId>
  4. </dependency>

3.2.2 application.properties 配置模板

主要配置,如下:

  1. ## Freemarker 配置
  2. spring.freemarker.template-loader-path=classpath:/templates/
  3. spring.freemarker.cache=false
  4. spring.freemarker.charset=UTF-8
  5. spring.freemarker.check-template-location=true
  6. spring.freemarker.content-type=text/html
  7. spring.freemarker.expose-request-attributes=false
  8. spring.freemarker.expose-session-attributes=false
  9. spring.freemarker.request-context-attribute=request
  10. spring.freemarker.suffix=.ftl
配置项 类型 默认值 建议值 说明
spring.freemarker.template-loader-path String classpath:/templates/ 默认 模版存放路径
spring.freemarker.cache bool true 默认 是否开启缓存,生成环境建议开启
spring.freemarker.charset String - UTF-8 编码
spring.freemarker.content-type String text/html text/html content-type类型
spring.freemarker.suffix String .ftl .ftl 模板后缀
spring.freemarker.expose-request-attributes bool false false 设定所有request的属性在merge到模板的时候,是否要都添加到model中
spring.freemarker.expose-session-attributes bool false false 设定所有HttpSession的属性在merge到模板的时候,是否要都添加到model中.
spring.freemarker.request-context-attribute String - request RequestContext属性的名称

更多配置:

  1. # FREEMARKER (FreeMarkerProperties)
  2. spring.freemarker.allow-request-override=false # Whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name.
  3. spring.freemarker.allow-session-override=false # Whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name.
  4. spring.freemarker.cache=false # Whether to enable template caching.
  5. spring.freemarker.charset=UTF-8 # Template encoding.
  6. spring.freemarker.check-template-location=true # Whether to check that the templates location exists.
  7. spring.freemarker.content-type=text/html # Content-Type value.
  8. spring.freemarker.enabled=true # Whether to enable MVC view resolution for this technology.
  9. spring.freemarker.expose-request-attributes=false # Whether all request attributes should be added to the model prior to merging with the template.
  10. spring.freemarker.expose-session-attributes=false # Whether all HttpSession attributes should be added to the model prior to merging with the template.
  11. spring.freemarker.expose-spring-macro-helpers=true # Whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext".
  12. spring.freemarker.prefer-file-system-access=true # Whether to prefer file system access for template loading. File system access enables hot detection of template changes.
  13. spring.freemarker.prefix= # Prefix that gets prepended to view names when building a URL.
  14. spring.freemarker.request-context-attribute= # Name of the RequestContext attribute for all views.
  15. spring.freemarker.settings.*= # Well-known FreeMarker keys which are passed to FreeMarker's Configuration.
  16. spring.freemarker.suffix=.ftl # Suffix that gets appended to view names when building a URL.
  17. spring.freemarker.template-loader-path=classpath:/templates/ # Comma-separated list of template paths.
  18. spring.freemarker.view-names= # White list of view names that can be resolved.

3.2.3 编写HTML代码

  1. <html>
  2. <head>
  3. <title>王磊的博客</title>
  4. </head>
  5. <body>
  6. <div>
  7. Hello,${name}
  8. </div>
  9. </body>
  10. </html>

3.2.4 编写Java代码

新建index.java文件,Application.java(入口文件)代码不便,index.java代码如下:

  1. import org.springframework.stereotype.Controller;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.servlet.ModelAndView;
  4. @Controller
  5. @RequestMapping("/")
  6. public class Index {
  7. @RequestMapping("/")
  8. public ModelAndView index() {
  9. ModelAndView modelAndView = new ModelAndView("/index");
  10. modelAndView.addObject("name", "老王");
  11. return modelAndView;
  12. }
  13. }

关键代码解读:

  1. @Controller注解:标识自己为控制器,只需要配置@RequestMapping之后,就可以把用户URL映射到控制器;
  2. 使用ModelAndView对象,指定视图名&添加视图对象。

3.2.5 运行

执行上面4个步骤之后,就可以运行这个Java项目了,如果是IDEA使用默认快捷键“Shift + F10”启动调试,在页面访问:http://localhost:8080/ 就可看到如下效果:

四、参考资料

FreeMarker官方文档:https://freemarker.apache.org/

FreeMarker翻译的中文网站:http://freemarker.foofun.cn/toc.html

Spring Boot (三)模板引擎FreeMarker集成的更多相关文章

  1. SpringBoot系列:Spring Boot使用模板引擎FreeMarker

    一.Java模板引擎 模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档. 在jav ...

  2. Spring Boot整合模板引擎freemarker

    jsp本质是servlet,渲染都在服务器,freemarker模板引擎也是在服务器端渲染. 项目结构 引入依赖pom.xml <!-- 引入 freemarker 模板依赖 --> &l ...

  3. spring boot: freemarket模板引擎

    spring boot: freemarket模板引擎 freemarket模板引擎,可以和thymeleaf模板引擎共存 pom.xml引入 <!-- Freemarket --> &l ...

  4. spring boot: thymeleaf模板引擎使用

    spring boot: thymeleaf模板引擎使用 在pom.xml加入thymeleaf模板依赖 <!-- 添加thymeleaf的依赖 --> <dependency> ...

  5. SpringBoot系列:Spring Boot使用模板引擎Thymeleaf

    一.Java模板引擎 模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档. 在jav ...

  6. SpringBoot系列:Spring Boot使用模板引擎JSP

    一.Java模板引擎 模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档. 在jav ...

  7. Spring boot 梳理 - 模版引擎 -freemarker

    开发环境中关闭缓存 spring: thymeleaf: cache: false freemarker: cache: false Spring boot 集成 freemarker <dep ...

  8. Spring Boot Thymeleaf 模板引擎的使用

    Spring Boot 中可以支持很多模板引擎,Thymeleaf 是 Spring Boot 官方推荐使用的模板引擎,虽然在社区 Thymeleaf 的性能被许多人所吐糟,但这仍然不影响大量的开发人 ...

  9. Spring Boot整合模板引擎thymeleaf

    项目结构 引入依赖pom.xml <!-- 引入 thymeleaf 模板依赖 --> <dependency> <groupId>org.springframew ...

随机推荐

  1. 高级查询query

    详细看 https://www.kancloud.cn/ldkt/tp5_db/229042

  2. Linux下好用的屏幕录像软件kazam及截图软件shutter

    都是apt直接安装即可使用. 其中kazam默认保存的文件格式是avi,非常大,通常录制几十秒就已经好几个G,导致录制过程太占用资源,会出现卡顿的现象. 在“首选项”中可以选择输出格式为mp4,文件就 ...

  3. pycharm无法使用ctrl+c/v复制粘贴的问题

    最近在使用pycharm的时候发现不能正常使用ctrl+c/v进行复制粘贴,也无法使用tab键对大段代码进行整体缩进.后来发现是因为安装了vim插件的问题,在setting里找到vim插件,取消勾选即 ...

  4. JUnit学习笔记-0-JUnit启动类

    [说明]:本文基于JUnit4.13版本代码,JDK1.8.0_151环境,使用工具为Eclipse,版本为Oxygen.1a Release (4.7.1a) [图示]: [正文]:JUnit4.1 ...

  5. SAwUML – UML-based, contractual software architectures and their formal analysis using SPIN

    一.基本信息 标题:SAwUML – UML-based, contractual software architectures and their formal analysis using SPI ...

  6. HelloWorld带我入门JAVA(一)

    基本环境配置可以百度完成,给个比较全面的网址http://c.biancheng.net/java/10/ 创建第一个java工程 通过Eclipse运行程序 启动Eclipse,在菜单中选择“文件 ...

  7. IDEA的Database管理台如何显示

    1.找出database的显示view 2.点击设置数据库,下载驱动文件,直接点击下载就行了,用什么数据库就下什么 3.填写服务器地址和用户名密码,点击测试,成功就表示连上了 4.一些常用按钮 5.目 ...

  8. android hal 诠释

    历史原因使Android系统有了HAL,它的角色相当于一个中间人,对上层,它负责给JNI提供调用kernel的方法,对下层,它所提供的方法包含能够访问kernel的函数,即kernel提供给上层的AP ...

  9. C#算法与数据结构之线性结构

    线性结构是什么? 线性结构是一种数据结构,它有一对一的关系,就像一个长对,一个接一个,特点是,除第一个元素和最后一个元素外,其它元素前后只有一个元素. 简单示例1: static void Main( ...

  10. 大叔学ML第三:多项式回归

    目录 基本形式 小试牛刀 再试牛刀 调用类库 基本形式 上文中,大叔说道了线性回归,线性回归是个非常直观又简单的模型,但是很多时候,数据的分布并不是线性的,如: 如果我们想用高次多项式拟合上面的数据应 ...