1. 使用Spring Initer快速构建SpringBoot工程,并选择需要的相关的依赖
2. FreeMarker 核心指令的练习
编写测试所用的实体类(Entity.Student)、Controller 类(Controller.freemarkerController) 以及 resources下的配置文件application.yml 还有在resources/templates目录下创建 test1.ftl
package com.example.freemarker.Entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
/* 关于 Lombok 详细注解请参考 https://blog.csdn.net/qq_38179971/article/details/105037988 这篇文章 */
@Repository
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Student {
private String name;
private Integer age;
private Date birthday;
private Float money;
private List<Student> friends;
private Student bestFriend;
}
package com.example.freemarkertest.Controller;
import com.example.freemarkertest.Entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.*;
import java.util.List;
@Controller
public class freemarkerController {
@RequestMapping("/test1")
public String test1(Map<String,Object> map){
/* 普通字符串 */
map.put("name","杨超越");
Student stu = new Student("stu",11,new Date(),1.11f,null,null);
Student stu2 = new Student("stu2",22,new Date(),2.22f,null,null);
Student stu3 = new Student("stu3",33,new Date(),3.33f,null,null);
Student stu4 = new Student("stu4",44,new Date(),4.44f,null,null);
/* List 集合 */
List<Student> students = new ArrayList<>();
stu.setFriends(students);stu2.setFriends(students);stu3.setFriends(students);stu4.setFriends(students);
stu.setBestFriend(stu2);stu2.setBestFriend(stu3);stu3.setBestFriend(stu4);stu4.setBestFriend(stu);
students.add(stu);students.add(stu2);students.add(stu3);students.add(stu4);
map.put("students",students);
/* HashMap 集合 */
HashMap<String,Student> hashMap = new HashMap();
hashMap.put("stu",stu);hashMap.put("stu2",stu2);hashMap.put("stu3",stu3);hashMap.put("stu4",stu4);
map.put("hashMap",hashMap);
/* 内建函数 之 日期转换 */
Date today = new Date();
map.put("today",today);
/* 内建函数 之 内建函数C */
map.put("number",1234567890);
return "test1";
}
}
# application.yml
server:
port: 8080 # 服务端口
spring:
application:
name: freemarker-test # 指定服务名
freemarker:
cache: false #关闭模板缓存,方便测试
settings:
template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试
suffix: .ftl
template-loader-path: classpath:/templates/
charset: UTF-8
check-template-location: true
content-type: text/html
expose-session-attributes: true # 设定所有HttpSession的属性在merge到模板的时候,是否要都添加到model中.
expose-request-attributes: true # 设定所有request的属性在merge到模板的时候,是否要都添加到model中.
request-context-attribute: request # 指定RequestContext属性的名.
<!-- 在 resources/templates 目录下创建 test1.ftl -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>UserList</title>
</head>
<style>
table tr td{
border: 1px solid darkcyan
}
div {
border-bottom: 1px solid mediumpurple;
padding-bottom: 20px;
}
</style>
<body>
<div>
<#-- 普通字符串 -->
<h5>模板中普通字符串的输出</h5>
${name}的第一个FreeMaker模板页面
</div>
<div>
<#-- 模板中使用list指令遍历数据类型中的数据 -->
<h5>模板中使用list指令遍历数据类型中的数据</h5>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
<#-- 判断某变量是否存在使用 “??” 用法为:variable??,如果该变量存在,返回true,否则返回false -->
<#if students??>
<#list students as stu>
<tr>
<td>${stu_index +1}</td>
<td>${stu.name}</td>
<td>${stu.age}</td>
<td>${stu.money!'money为空'}</td>
</tr>
</#list>
</#if>
</table>
</div>
<#-- 模板中使用map指令遍历数据类型中的数据 -->
<div>
<h5>输出hashMap中单条数据的信息</h5>
姓名:${hashMap.stu.name}<br/>
年龄:${hashMap.stu.age}<br/>
</div>
<div>
<h5>遍历输出hashMap中所有数据的信息</h5>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
<#list hashMap?keys as k>
<tr>
<td>${k_index + 1}</td>
<td>${hashMap[k].name}</td>
<td>${hashMap[k].age}</td>
<td>${hashMap[k].money!'money为空'}</td>
</tr>
</#list>
</table>
</div>
<div>
<h5>模板中if指令的使用</h5>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
<#if students??>
<#list students as stu>
<tr>
<td>${stu_index +1}</td>
<td <#if stu.name == 'stu2'>style="background:green;"</#if>>${stu.name}</td>
<td>${stu.age}</td>
<td>${stu.money!'money为空'}</td>
</tr>
</#list>
</#if>
</table>
</div>
<div>
<h5>内建函数 之 集合大小</h5>
${students?size}
</div>
<div>
<h5>内建函数 之 日期格式化</h5>
显示年月日: ${today?date} <br/>
显示时分秒: ${today?time} <br/>
显示日期+时间: ${today?datetime} <br/>
自定义格式化: ${today?string("yyyy年MM月dd日 HH时mm分ss秒")} <br/>
</div>
<div>
<h5>内建函数 之 内建函数C</h5>
原样输出数字:${number}<br/>
使用 内建函数C 将数字转换成字符后输出:${number?c}
</div>
<div>
<h5>使用内建函数assign 将JSON字符串转成对象</h5>
<#assign text="{'bank':'农业银行','account':'6228483169215254871'}" />
<#assign data=text?eval />
开户行:${data.bank} 账户:${data.account}
</div>
</body>
</html>
运行 FreemarkerTestApplication.java 启动类后 浏览器输入 localhost:8080/test1
3. 其他指令
3.1 运算符
3.1.1 算数运算符 FreeMarker表达式中完全支持算术运算,FreeMarker支持的算术运算符包括:+, - , * , / , %
3.1.2 逻辑 运算符 逻辑运算符有如下几个: 逻辑与:&& 逻辑或:|| 逻辑非:! 逻辑运算符只能作用于布尔值,否则将产生错误
3.1.3 比较运算符 表达式中支持的比较运算符有如下几个: 1 =或者==:判断两个值是否相等. 2 !=:判断两个值是否不等. 3 > 或者gt:判断左边值是否大于右边值
3.1.4 >=或者gte:判断左边值是否大于等于右边值
3.1.5 会有更好的效果,因为 FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括 号来避免这种情况,如:y)>
3.2 空值处理
3.2.1 判断某变量是否存在使用 “??” 用法为:variable??,如果该变量存在,返回true,否则返回false 例:为防止stus为空报错可以加上判断如下:
<#if stus??>
<#list stus as stu>
......
</#list>
</#if>
3.2.2 缺失变量默认值使用 “!” 使用!要以指定一个默认值,当变量为空时显示默认值。 例: ${name!''}表示如果name为空显示空字符串。 如果是嵌套对象则建议使用()括起来。例如 ${(stu.bestFriend.name)!''} 的表示,如果stu或bestFriend或name为空默认显示空字符串。
4. 静态化生成HTML文件的俩种方式
如下图所示在test目录下建立 testFreemarkerGenerator.java 和 test2.ftl 俩个文件
└─test
├─java
│ testFreemarkerGenerator.java
│
└─resources
└─templates
test2.ftl
/* "testFreemarkerGenerator.java" */
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class testFreemarkerGenerator {
/* 基于模板生成静态化文件夹 */
@Test
public void testGenerateHtml() throws IOException, TemplateException {
/* 创建配置类 */
Configuration configuration = new Configuration(Configuration.getVersion());
/* 设置模板路径 */
String classpath = this.getClass().getResource("/").getPath();
configuration.setDirectoryForTemplateLoading(new File(classpath + "/templates/"));
/* 设置字符集 */
configuration.setDefaultEncoding("UTF-8");
/* 加载模板 */
Template template = configuration.getTemplate("test2.ftl");
/* 数据模型 */
Map<String,Object> map = new HashMap<>();
map.put("name","杨超越");
/* 静态化 */
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template,map);
/* 静态化内容 */
System.out.println(content);
InputStream inputStream = IOUtils.toInputStream(content);
/* 输出文件 */
FileOutputStream fileOutputStream = new FileOutputStream(new File("D:/test21.html"));
Integer copy = IOUtils.copy(inputStream,fileOutputStream);
}
/* 基于模板字符串生成静态化文件 */
@Test
public void testGeneratorHtmlByString() throws IOException, TemplateException {
/* 创建配置类 */
Configuration configuration = new Configuration(Configuration.getVersion());
/* 模板的内容: 这里使用简单的字符串作为模板 */
String templateString =
"<html>\n" +
" <head></head>\n" +
" <body>\n" +
" 这是${name}的第一个FreeMarker模板文件\n" +
" </body>\n" +
"</html>";
/* 模板加载器 */
StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
stringTemplateLoader.putTemplate("template",templateString);
configuration.setTemplateLoader(stringTemplateLoader);
/* 得到模板 */
Template template = configuration.getTemplate("template","utf-8");
/* 数据模型 */
Map<String,Object> map = new HashMap<>();
map.put("name","欧阳娜娜");
/* 静态化 */
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template,map);
/* 静态化内容 */
System.out.println(content);
InputStream inputStream = IOUtils.toInputStream(content);
/* 输出文件 */
FileOutputStream fileOutputStream = new FileOutputStream(new File("D:/test22.html"));
IOUtils.copy(inputStream,fileOutputStream);
}
}
<!-- test2.ftl -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>UserList</title>
</head>
<style>
table tr td{
border: 1px solid darkcyan
}
div {
border-bottom: 1px solid mediumpurple;
padding-bottom: 20px;
}
</style>
<body>
<div>
<#-- 普通字符串 -->
<h5>模板中普通字符串的输出</h5>
${name}的第一个FreeMaker模板页面
</div>
</body>
</html>
4.1 使用模板文件静态化 定义模板文件,使用freemarker静态化程序生成html文件
运行 第一个测试方法 testGenerateHtml(),会发现 D盘下多出一个 test21.html 文件,打开该网页,与预期效果相符,测试成功。
4.2 使用模板字符串静态化 定义模板字符串,使用freemarker静态化程序生成html文件。
运行 第一个测试方法 testGenerateHtmlByString(),会发现 D盘下多出一个 test22.html 文件,打开该网页,与预期效果相符,测试成功。