标量类型 Scalars 的显示
插值 Interpolations , 即在模板中插入一个值 。例如,${cellphone} 就是插值,大括号里称为表达式 (expression)。插值类型有很多,我们先来学习4种标量类型的使用( 标量 Scalars )。
- String 字符串、Number 数字、Boolean 布尔、Date-like 日期/时间
参考官方文档 Template Author's Guide | Values, Types|The types https://freemarker.apache.org/docs/dgui_datamodel_types.html#dgui_datamodel_scalar
- 标量在显示时,可以用一个内置的格式转换方法。
例如 ${id?c} ${birthday?date} ${sex?then('男', '女')} ,其中,问号后面表示的是转换方法。
参考:Template Language Reference | Built-in Reference https://freemarker.apache.org/docs/ref_builtins.html
例子
模板网页 a1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>freemarker</title>
</head>
<body>
<div>
<label> 学号: </label> ${id?c} <br>
<label> 姓名: </label> ${name} <br>
<label> 手机: </label> ${cellphone} <br>
<label> 性别: </label> ${sex?then('男','女')} <br>
<label> 性别: </label> ${birthday?date} <br>
</div>
</body>
</html>
使用这个模板
public class Test
{
public static void main(String[] args) throws TemplateException, IOException
{
// 初始化FreeMarker ( 模板库 )
Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
cfg.setDirectoryForTemplateLoading(new File("template")); // 指定模板根目录
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setLogTemplateExceptions(false);
// 创建数据模型(data-model)
Map<String,Object> model = new HashMap<String,Object>();
model.put("id", 2021001);
model.put("name", "li");
model.put("cellphone", "1234567890");
model.put("sex", true);
model.put("birthday", new Date());
// 提取模板 (template)
Template tp = cfg.getTemplate("a1.html"); // template/a1.html
// 合成输出 (output) : 直接输出到控制台显示
Writer out = new OutputStreamWriter(System.out);
tp.process(model, out);
}
}
控制台得到的结果
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>freemarker</title>
</head>
<body>
<div>
<label> 学号: </label> 2021001 <br>
<label> 姓名: </label> li <br>
<label> 手机: </label> 1234567890 <br>
<label> 性别: </label> 男 <br>
<label> 性别: </label> 2021-4-8 <br>
</div>
</body>
</html>
容器类型 Containers 的显示
容器类型分为3种:
- Hash : 哈希类型: 如Map , HashMap - Sequence
- 顺序类型: 如数组, List, ArrayList - Collection
- 集合类型: 如 Set
参考Template Author's Guide | Values, Types|The types https://freemarker.apache.org/docs/dgui_datamodel_types.html#dgui_datamodel_container
模板网页a1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>freemarker</title>
</head>
<body>
<div>
<label> 学号: </label> ${id?c} <br>
<label> 姓名: </label> ${name} <br>
<label> 手机: </label> ${cellphone} <br>
<label> 性别: </label> ${sex?then('男','女')} <br>
<label> 生日: </label> ${birthday?date} <br>
<div>
语文 : ${score.chinese} <br>
数学 : ${score.math} <br>
英语 : ${score.english} <br>
</div>
<div>
头号朋友: ${friends[0]}
朋友列表:
<#list friends as item>
${item}
</#list>
</div>
</div>
</body>
</html>
- 哈希类型在模板中用点号访问子变量,例如 ${score.english} 。
- 顺序类型在模板中用下标访问 ${friends[0]} 或用 <#list ..> </#list>遍历。以#开头的标签是FreeMarker标签。
public class Test
{
public static void main(String[] args) throws TemplateException, IOException
{
// 初始化FreeMarker ( 模板库 )
Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
cfg.setDirectoryForTemplateLoading(new File("template")); // 指定模板根目录
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setLogTemplateExceptions(false);
// 创建数据模型(data-model)
Map<String,Object> model = new HashMap<String,Object>();
model.put("id", 2021001);
model.put("name", "li");
model.put("cellphone", "1234567890");
model.put("sex", true);
model.put("birthday", new Date());
// 添加一个 Hash
Map<String, Object> score = new HashMap<String, Object>();
score.put("chinese", 90);
score.put("english", 87);
score.put("math", 93);
model.put("score", score); // 加入model
// 也可以添加一个 Sequence
List<String> friends = new ArrayList<String>();
friends.add("露露");
friends.add("梅梅");
friends.add("露西");
friends.add("莉莉");
model.put("friends", friends); // 加入model
// 提取模板 (template)
Template tp = cfg.getTemplate("a1.html"); // template/a1.html
// 合成输出 (output) : 直接输出到控制台显示
Writer out = new OutputStreamWriter(System.out);
tp.process(model, out);
}
}
控制台得到的结果的显示
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>freemarker</title>
</head>
<body>
<div>
<label> 学号: </label> 2021001 <br>
<label> 姓名: </label> li <br>
<label> 手机: </label> 1234567890 <br>
<label> 性别: </label> 男 <br>
<label> 生日: </label> 2021-4-8 <br>
<div>
语文 : 90 <br>
数学 : 93 <br>
英语 : 87 <br>
</div>
<div>
头号朋友: 露露
朋友列表:
露露
梅梅
露西
莉莉
</div>
</div>
</body>
</html>
POJO类型的显示
在模板里也支持POJO的显示 ( 归为 Hash类型,在模板里用点号访问)。
添加一个Book对象,在模板里插值。POJO的要求:只需要getter即可。 例如,在模板里有 ${book.price} ,则FreeMarker会调用 book.getPrice() 方法取值。
注:显然,在Book类里不管有没有price这个属性,都并不影响取值,只要Book类里有getPrice()方法即可。
模板网页a1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>freemarker</title>
</head>
<body>
<div>
书名: ${book.title} <br>
作者: ${book.author} <br>
ISBN: ${book.isbn} <br>
书版社: ${book.press} <br>
订价: ${book.price} <br>
</div>
</body>
</html>
pojo类
package my;
/* POJO: 只需要getter即可
*/
public class Book
{
public String title;
public String author;
public String isbn;
public String press;
public double getPrice()
{
return 50;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getAuthor()
{
return author;
}
public void setAuthor(String author)
{
this.author = author;
}
public String getIsbn()
{
return isbn;
}
public void setIsbn(String isbn)
{
this.isbn = isbn;
}
public String getPress()
{
return press;
}
public void setPress(String press)
{
this.press = press;
}
}
public class Test
{
public static void main(String[] args) throws TemplateException, IOException
{
// 初始化FreeMarker ( 模板库 )
Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
cfg.setDirectoryForTemplateLoading(new File("template")); // 指定模板根目录
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setLogTemplateExceptions(false);
// 创建数据模型(data-model)
Map<String,Object> model = new HashMap<String,Object>();
// 也可以添加一个POJO
Book b = new Book();
b.title = "C/C++";
b.author = "li";
b.isbn = "978730123";
b.press = "大学出版社";
model.put("book", b);// 加入model
// 提取模板 (template)
Template tp = cfg.getTemplate("a1.html"); // template/a1.html
// 合成输出 (output) : 直接输出到控制台显示
Writer out = new OutputStreamWriter(System.out);
tp.process(model, out);
}
}
控制台输出
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>freemarker</title>
</head>
<body>
<div>
书名: C/C++ <br>
作者: li <br>
ISBN: 978730123 <br>
书版社: 大学出版社 <br>
订价: 50 <br>
</div>
</body>
</html>
如果模板里有语法错误,则freemarker会抛异常提示。 当一个插值为空或不存在的时候,都会报错 ( The following has evaluated to null or missing)。
比如b.title = null; 或者模板里写错成 ${book.titlet} 都会报异常。
空值的处理
Missing Variables 指一个变量的值为null , 或者该变量不存在 ,当这种情况发生时,FreeMarker会报错提示。
参考:Template Author's Guide | Getting Started | The template at a glance | Dealing with missing variables https://freemarker.apache.org/docs/dgui_quickstart_template.html#autoid_8
当出现空值时,FreeMarker报错如下: The following has evaluated to null or missing
- 解决办法: ${expression ! defValue } 用叹号分隔来设置一个缺省值。
- 当对多级子变量进行判断时, ${ a.b.c } 如果 a有可能null ,a.b 有可能为null ,或者 a.b.c有可能为null,统一适用 ( 加一个小括号 ): $ { (a.b.c) ! defValue }
例如
${(book.title)!'暂无数据'}