一、freemarker介绍
- FreeMarker 是一款 模板引擎
- 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件
- 模板编写为FreeMarker Template Language(FTL)
- 它是简单的,专用的语言,不是像PHP那样成熟的变成语言。那就意味着要准备数据在在真实编程语言中来显示,比如数据库查询和业务运算,之后模板显示以及准备好的数据。在模板中,可以更加专注于如何展现数据,而在模板之外可以专注于要展示什么数据
二、freemarker环境搭建&&快速入门
需要创建Spring Boot + Freemarker 工程用于测试模板
2.1、创建测试工程
- 创建一个freemark-demo的测试工程用于freemarker的功能测试与模板测试
- POM文件如下所示
- <?xml version="1.0" encoding="UTF-8"?>
- <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.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.coolman</groupId>
- <artifactId>freemarker-demo</artifactId>
- <version>1.0-SNAPSHOT</version>
- <properties>
- <maven.compiler.source>8</maven.compiler.source>
- <maven.compiler.target>8</maven.compiler.target>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-freemarker</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- </dependency>
- </dependencies>
- </project>
复制代码
2.2、配置文件
- application.yml文件如下所示
- server:
- port: 9527
- spring:
- application:
- name: freemarker-demo # 指定服务名
- freemarker:
- cache: false # 关闭缓存,方便测试
- settings:
- template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试
- suffix: .ftl #指定Freemarker模板文件的后缀名
- template-loader-path: classpath:/templates #指定模板文件存放的位置
复制代码
2.3、创建启动类
- 启动类如下所示
- package com.coolman.freemarker;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- @SpringBootApplication
- public class FreemarkerApplication {
- public static void main(String[] args) {
- SpringApplication.run(FreemarkerApplication.class, args);
- }
- }
复制代码
2.4、创建模型类
- 在freemarker的测试工程下创建模型类型用于测试
- package com.coolman.freemarker.model;
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public class Person {
- private String name;
- private Integer age;
- }
复制代码
2.5、创建模板
- 在resources下创建templates,并创建模板文件freemarker.ftl文件(模板中的插值表达式最终会被freemarker替换成具体的数据)
- 编写一个简单的HTML模板
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>Hello Freemarker!</title>
- </head>
- <body>
- <b>普通文本 String 展示:</b>
- Welcome to SuperCoolMan's home !!
- I’m 99 years old this year !!
- <hr>
- <hr>
- </body>
- </html>
复制代码
2.6、创建测试类并测试
- 创建Controller类,添加数据,最后返回模板文件
- 测试1:
- package com.coolman.freemarker.controller;
- import freemarker.template.Configuration;
- import freemarker.template.Template;
- import freemarker.template.TemplateException;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.util.HashMap;
- @RestController
- @RequestMapping("/freemarker")
- public class FreemarkerController {
- // 引入freemarker.template包下的Configuration类,用来获取指定的模板对象
- @Autowired
- private Configuration configuration;
- /**
- * 通过模板文件,生成html文件
- */
- @GetMapping("/test")
- public String getHtml() {
- try {
- // 使用Configuration的getTemplate方法,指定模板文件,获取模板对象
- Template template = configuration.getTemplate("HelloFreemarker.ftl");
- // 绑定数据
- // 数据1:
- HashMap<String, Object> map = new HashMap<>();
- map.put("name", "SuperCoolMan");
- map.put("age", 99);
- FileWriter fileWriter = new FileWriter("E:\\系统默认\\桌面\\news-init\\freemarker-demo\\src\\main\\resources\\testHtml\\HelloFreemarker.html");
- template.process(map, fileWriter);
- return "SUCCESS!";
- } catch (IOException | TemplateException e) {
- e.printStackTrace();
- }
- return "ERROR!";
- }
- }
复制代码- 浏览器打开生成的静态文件
- 修改Controller中的方法,添加Person对象数据
- package com.coolman.freemarker.controller;
- import com.coolman.freemarker.model.Person;
- import freemarker.template.Configuration;
- import freemarker.template.Template;
- import freemarker.template.TemplateException;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.util.HashMap;
- @RestController
- @RequestMapping("/freemarker")
- public class FreemarkerController {
- // 引入freemarker.template包下的Configuration类,用来获取指定的模板对象
- @Autowired
- private Configuration configuration;
- /**
- * 通过模板文件,生成html文件
- */
- @GetMapping("/test")
- public String getHtml() {
- try {
- // 使用Configuration的getTemplate方法,指定模板文件,获取模板对象
- Template template = configuration.getTemplate("HelloFreemarker.ftl");
- // 绑定数据
- // 数据1:
- HashMap<String, Object> map = new HashMap<>();
- map.put("name", "SuperCoolMan");
- map.put("age", 99);
- // 数据2:
- map.put("person", new Person("超级猛男", 18));
- FileWriter fileWriter = new FileWriter("E:\\系统默认\\桌面\\news-init\\freemarker-demo\\src\\main\\resources\\testHtml\\HelloFreemarker.html");
- template.process(map, fileWriter);
- return "SUCCESS!";
- } catch (IOException | TemplateException e) {
- e.printStackTrace();
- }
- return "ERROR!";
- }
- }
复制代码- 修改模板
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>Hello Freemarker!</title>
- </head>
- <body>
- <b>普通文本 String 展示:</b>
- Welcome to ${name}'s home !!
- I’m ${age} years old this year !!
- <hr>
- <b>对象Person中的数据展示:</b><br/>
- 姓名:${person.name}<br/>
- 年龄:${person.age}
- <hr>
- </body>
- </html>
复制代码
- 浏览器打开生成的静态文件
2.7、总结
三、freemarker语法指令
3.1、基础语法
3.1.1、注释
- 注释,即,介于其之间的内容会被freemarker忽略
- [/code]
- [/list]
- [/list][size=4]3.1.2、插值[/size]
- [list]
- [*]插值(Interpolation):即${<#if >...</#if>}部分,freemarker会用真实的值代替${}(PS:如果返回的数据中没有该真实值,freemarker服务会直接报错)
- [list]
- [*][code]Welcome to ${name}'s home
复制代码
3.1.3、FTL指令
- FTL指令:和HTML标记类似,名字前加#予以区分,Freemarker会解析标签中的表达式或逻辑
3.1.4、文本
- 文本,仅文本信息,这些不是freemarker的注释、插值、FTL指令的内容会被freemarker忽略解析,直接输出内容
- <#--freemarker中的普通文本-->
- 我是一个普通的文本
复制代码
3.2、集合指令(List、Map)
接下来的测试,只截取部分代码,直接在原代码的基础上增加即可
- 为了Controller尽可能简略,创建一个getData方法,返回一个Map集合,Controller方法直接调用这个getData生成测试数据即可
- private Map<String, Object> getData() {
- HashMap<String, Object> map = new HashMap<>();
- // String类型:
- map.put("name", "SuperCoolMan");
- map.put("age", 99);
- // Person类型:
- map.put("person", new Person("超级猛男", 18));
-
- //
- return map;
- }
复制代码
3.2.1、List集合
- Controller
- // List集合类型
- ArrayList<Person> list = new ArrayList<>();
- list.add(new Person("瞳夕", 18));
- list.add(new Person("二呆", 18));
- list.add(new Person("嘿嘿", 18));
- map.put("wifeList", list);
复制代码
- 模板
- <b>List类型中的数据展示:</b><br/>
- <#list wifeList as wife>
- 序号:${wife_index + 1} <br/> <#--freemarker中FTL指令自带的序号属性,默认从0开始-->
- 姓名:${wife.name} <br/>
- 年龄:${wife.age} <br/><br/>
- </#list>
- <hr>
复制代码
- 最终效果
3.2.2、Map集合
- Controller
- // Map集合类型
- HashMap<String, Object> anOtherMap = new HashMap<>();
- anOtherMap.put("smallWife1", new Person("莫妮卡", 18));
- anOtherMap.put("smallWife2", new Person("玛丽莲梦露", 18));
- map.put("smallWife", anOtherMap);
复制代码
- 模板
- <b>Map + Person 类型中的数据展示:</b><br/>
- <b>方式一:通过map['keyname'].property 输出对应信息:</b><br/>
- 性别:${wifeMap['smallWife1'].name} <br/>
- 年龄:${wifeMap['smallWife1'].age} <br/>
- <b>方式二:通过map.keyname.property 输出对应信息:</b><br/>
- 性别:${wifeMap.smallWife2.name} <br/>
- 年龄:${wifeMap.smallWife2.age} <br/>
- <hr>
复制代码
- 最终效果
- 遍历Map集合
- 模板
- <b>遍历Map中多个Person信息:</b><br/>
- <#list wifeMap?keys as key>
- 序号:${key_index} <br/>
- 性别:${key.name} <br/>
- 年龄:${key.age} <br/><br/>
- </#list>
- <hr>
复制代码
- 最终效果
3.3、if指令
- if指令即判断指令,是常用的FTL指令,freemarker在解析的时候遇到if会进行判断,条件为真则输出if中间的内容,否则跳过内容不在输出
- Controller
- // if test
- map.put("score", 88);
复制代码
- 模板
- <b>if指令测试:</b><br/>
- <#if (score > 90)>
- 继续努力
- <#elseif (score > 80)>
- 面包总会有的
- <#else>
- 革命尚未成功,同志仍需努力
- </#if>
- <hr>
复制代码
- 最终效果
3.4、空值处理
3.4.1、判断某变量是否存在
- 语法格式
- 如果该变量存在,返回true,否则返回false
- 如下例所示
- <#if >...</#if><#if >...</#if>
复制代码
3.4.2、缺失变量默认值
- 使用!要指定一个默认值,当变量为空的时候显示默认值
- 例:${name!'默认值'}表示如果name为空,显示默认值
- 如果是嵌套对象则建议使用()括起来
- 例:${(stu.bestFriend.name)!"默认值"}表示如果stu或者bestFriend或者name为空默认显示默认值
3.5、内建函数
3.5.1、获取集合大小
3.5.2、日期格式化
- 后端返回一个Date对象,模板要取值,则如下所示
- map.put("today",new Date())
- 显示年月日
- 显示时分秒
- 显示日期+时间
- 自定义格式化
- ${today?string("yyyy年MM月")}
3.5.3、内建函数c(数字格式化)
- 后端返回一串数字,模板可以对其进行格式化,如下所示
- map.put("point", 102920122);
- point是数字型,使用${point}会显示这个数字的值,每三位使用逗号隔开
- 如果不像显示为每三位分隔的数字,可以使用c函数将数字转成字符串输出
- 指令格式如下所示
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |