0 freemarker简介

首先我们要先通过 官网:https://freemarker.apache.org/ 了解什么是freemarker 以及他的使用方法。官方介绍如下:

Apache FreeMarker™是一个模板引擎:一个Java库,用于根据模板和更改数据生成文本输出(HTML网页,电子邮件,配置文件,源代码等)。模板是用FreeMarker模板语言(FTL)编写的,这是一种简单的专用语言(不像PHP这样的完整编程语言)。通常,使用通用编程语言(如Java)来准备数据(发布数据库查询,进行业务计算)。然后,Apache FreeMarker使用模板显示准备好的数据。在模板中,您将关注如何呈现数据,而在模板之外,您将关注于要呈现的数据。

这种方法通常被称为MVC(模型视图控制器)模式,并且特别受动态网页的欢迎。它有助于将网页设计者(HTML作者)与开发人员(通常是Java程序员)分开。设计人员不会在模板中面对复杂的逻辑,并且可以在程序员不必更改或重新编译代码的情况下更改页面的外观。

虽然FreeMarker最初是为在MVC Web应用程序框架中生成HTML页面而创建的,但它并没有绑定到servlet或HTML或任何与Web相关的内容。它也用于非Web应用程序环境。

通过点击下图红色框文档手册 阅读如何使用 freemarker

接下来开始介绍freemarker 基本用法。介绍之前先说明一下我们的开发环境

0.1 版本说明

IDEA :STS

JDK:1.8

freemarker Version:2.3.28

这里将通过maven项目进行说明我们的用法。首先引入freemarker 依赖到我们的maven项目中

  <dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.28</version></dependency>

1 freemarker 用法之 Hello word

在resource目录下创建template目录并添加helloworld.ftl 模板文件 内容如下:

<html>
<head>  <title>hello world</title>
</head> <body> <h1>this is ${who} hello World</h1></body>
</html> 

创建配置实例 并将模板和数据进行输出

package cn.lijunkui.examples;import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;import org.junit.Test;import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;public class FreemarkerDemo {@Testpublic void helloWord() throws IOException, TemplateException {Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);//指定模板文件的来源String path = FreemarkerDemo.class.getClassLoader().getResource("template").getPath();cfg.setDirectoryForTemplateLoading(new File(path));//这是模板的编码cfg.setDefaultEncoding("UTF-8");//获取模板Template template = cfg.getTemplate("helloworld.ftl"); //创建FreeMarker的数据模型  Map<String,String> root = new HashMap<String,String>();  root.put("who","freemarker");//这是输出文件File file = new File("D://" +"helloWord.html");Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));//将模板与数据模型合并template.process(root, out); out.flush();  out.close();  }
}

2 data-model:数据模型

hello word的示例其实就是 Template + data-model = output 接下来我们引用一下官方的示例介绍一下数据模型

数据模型是树状结构 如下图

以上只是一个可视化; 数据模型不是文本格式,而是来自Java对象。对于Java程序员来说,root可能是带有getUser() 和getLatestProduct()方法的Java对象,或者是Map带有"user""latestProducts"键的Java 。同样, latestProduct也许是一个Java对象 getUrl()getName() 方法。

<html>
<head> <title>欢迎!</ title>
</head>
<body> <h1>欢迎${user}!</ h1> <p>我们的最新产品:<a href ="${latestProduct.url}"> ${latestProduct.name} </a>!
</body>
</html>
 @Testpublic void dataModel() throws IOException, TemplateException {Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);//指定模板文件的来源String path = FreemarkerDemo.class.getClassLoader().getResource("template").getPath();cfg.setDirectoryForTemplateLoading(new File(path));//这是模板的编码cfg.setDefaultEncoding("UTF-8");//获取模板Template template = cfg.getTemplate("data-model.ftl"); //创建FreeMarker的数据模型  Map<String,Object> root = new HashMap<String,Object>();  root.put("user","Big Joe");Product product = new Product();product.setName("绿色鼠标");product.setUrl("products/greenmouse.html");root.put("latestProduct",product);//这是输出文件File file = new File("D://" +"dataModel.html");Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));//将模板与数据模型合并template.process(root, out); out.flush();  out.close();  }

3 freemarker 注释

我们可以通过 <#-- 注释内容 --> 来进行注释 如下图

4 freemarker 条件指令

我们可以通过<#if>  <#elseIf> <#else> 进行条件判断逻辑处理 具体操作如下

条件指令模板内容:

<html>
<head> <title>条件指令介绍!</ title>
</head>
<body> <#-- 条件指令介绍 -->
<#if (5 > 4) > 5 比较大
</#if>
-------------------------------
<#if (!false)>!false == true
</#if>
-----------------------------
<#if ("a" == "b")>a 和 b 相同
<#else>a 和 b 不相同
</#if>
-----------------------------
<#if ( c == d)>c 和 d 相同 <#elseif ("a" != "b")>c 和 d 不相同<#else>出错了!
</#if>
</body>
</html>

条件指令测试用例:

这里我们对测试用例进行了封装,后面的测试用例都将调用 initTemplate 来进行测试

 @Testpublic void condition() throws IOException, TemplateException {Map root = new HashMap();root.put("c", "c");root.put("d", "d");initTemplate("condition",root);}public void initTemplate(String templateName,Map root) throws IOException, TemplateException {Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);//指定模板文件的来源String path = FreemarkerDemo.class.getClassLoader().getResource("template").getPath();cfg.setDirectoryForTemplateLoading(new File(path));//这是模板的编码cfg.setDefaultEncoding("UTF-8");//获取模板Template template = cfg.getTemplate(templateName+".ftl"); //创建FreeMarker的数据模型  //这是输出文件File file = new File("D://" +templateName+".html");Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));//将模板与数据模型合并template.process(root, out); out.flush();  out.close();  }

5 freemarker list 指令

我们可以通过 <#list 序列 as item>  来进行序列的遍历。另外list 还有一些内置的序列的函数

?size:序列的数量

_index :序列中元素的角标

_has_next:是否是当前迭代循环中的最后一项

?sort:对序列中的元素进行排序

?sort_by:根据实例中的具体的否个字段进行排序

?is_enumerable:是否是集合

测试list模板内容

<html>
<head> <title>list 指令介绍!</ title>
</head>
<body>
<#list 0..5 as item>${item}
</#list>
-----------------------------
_index:交标值 ,?size 获取集合的长度
list的长度:${wordList?size}
<#list wordList as word>当前的交标是:${word_index}值是:${word}
</#list>
--------------------------------
_has_next:是否是当前迭代循环中的最后一项
<#list wordList as word><#if word_has_next>不是最后一项:${word},<#else>是最后一项:${word}</#if>
</#list>
---------------------------------
字符串(按首字母排序),数字,日期值
正常遍历
<#list wordList as word>${word}
</#list>
升序
<#list wordList?sort as word>${word}
</#list>
降序
<#list wordList?sort?reverse as word>${word}
</#list>
反向遍历
<#list wordList?reverse as word>${word}
</#list>-------------------------------------
正常遍历
<#list productList as p>${p.name}#${p.url}#${p.saleNum}
</#list>
升序
<#list productList?sort_by("saleNum") as p>${p.name}#${p.url}#${p.saleNum}
</#list>
降序
<#list productList?sort_by("saleNum")?reverse as p>${p.name}#${p.url}#${p.saleNum}
</#list>
反向遍历
<#list productList?reverse as p>${p.name}#${p.url}#${p.saleNum}
</#list>
---------------------------------------
<#list map?keys as item><#if (item == "productMap3")><#list map[item] as p>${p.name}#${p.url}#${p.saleNum}                      </#list><#else>${map[item]}</#if>
</#list>
----------------------------------------
?is_string:是否是字符串
<#list map?keys as item><#if map[item]?is_string>${map[item]}<#else><#list map[item] as p>${p.name}#${p.url}#${p.saleNum}                      </#list></#if>
</#list>
-----------------------------------------
?is_enumerable:是否是集合
<#list map?keys as item><#if map[item]?is_enumerable><#list map[item] as p>${p.name}#${p.url}#${p.saleNum}                      </#list><#else>${map[item]}</#if>
</#list>
</body>
</html>

list模板内容测试用例:

 @Testpublic void list() throws IOException, TemplateException {Map root = new HashMap();List wordList = new ArrayList();wordList.add(5);wordList.add(3);wordList.add(6);root.put("wordList", wordList);List<Product> productList = new ArrayList<Product>();productList.add(new Product("123.html", "苹果", 5));productList.add(new Product("13.html", "香蕉", 3));productList.add(new Product("13.html", "芒果", 15));root.put("productList", productList);Map map = new HashMap();map.put("productMap", "a");map.put("productMap2", "b");map.put("productMap3", productList);root.put("map", map);initTemplate("list",root);}

list模板内容测试结果:

<html>
<head> <title>list 指令介绍!</ title>
</head>
<body> 012345
-----------------------------
_index:交标值 ,?size 获取集合的长度
list的长度:3当前的交标是:0值是:5当前的交标是:1值是:3当前的交标是:2值是:6
--------------------------------
_has_next:是否是当前迭代循环中的最后一项不是最后一项:5,不是最后一项:3,是最后一项:6---------------------------------
字符串(按首字母排序),数字,日期值
正常遍历5                    3                    6
升序3                    5                    6
降序6                    5                    3
反向遍历6                    3                    5                    -------------------------------------
正常遍历苹果#123.html#5                      香蕉#13.html#3                      芒果#13.html#15
升序香蕉#13.html#3                    苹果#123.html#5                    芒果#13.html#15
降序芒果#13.html#15                     苹果#123.html#5                     香蕉#13.html#3
反向遍历芒果#13.html#15                      香蕉#13.html#3                      苹果#123.html#5
---------------------------------------ab苹果#123.html#5                      香蕉#13.html#3                      芒果#13.html#15
----------------------------------------ab苹果#123.html#5                      香蕉#13.html#3                      芒果#13.html#15
-----------------------------------------ab苹果#123.html#5                      香蕉#13.html#3                      芒果#13.html#15
</body>
</html>

6 freemarker assign指令

我们可以通过 assign指令在ftl中进行值的定义

assign指令测试模板内容:

<#assign name="zhuoqianmingyue">
${name}
-----------------------------------------------------------
<#assign product={"name":"苹果","url":"123.html","saleNum":23} >
${product.name},${product.url},${product.saleNum}

assign指令测试用例:

 @Testpublic void assign() throws IOException, TemplateException {Map root = new HashMap();initTemplate("assign",root);}

assign指令测试结果:

7 创建宏

这里的宏 我们可以理解成创建方法。我们可以通过 <#macro>标签来定义宏。

创建宏模板内容如下

创建宏模板测试用例:

 @Testpublic void marco() throws IOException, TemplateException {Map map = new HashMap();initTemplate("macroShow", map);}

创建宏模板测试结果:

嵌套指令<#nested> 可以执行两次相同的调用

 @Testpublic void nested() throws IOException, TemplateException {Map map = new HashMap();initTemplate("nestedShow", map);}

8 include指令

include引入的文件内容freemarker将解析其中的freemarker语法并移交给模板,同时assign的值可以互相调用

include 引入ftl模板

parent.ftl

<html>
<body>
我是公共的页面 ${who}引用啦我!
</body>
</html>

include.ftl

我是include页面
<#assign who="include.ftl">
<#include "parent.ftl"/>

include指令的测试用例:

 @Testpublic void include() throws IOException, TemplateException {Map map = new HashMap();initTemplate("include", map);}

include指令的测试结果:

include 引入html

在resource 目录下创建include.html

模板内容:

测试用例:

 @Testpublic void include2() throws IOException, TemplateException {Map map = new HashMap();initTemplate("include2", map);}

测试结果:

9 import指令

import引入的文件内容freemarker将不会解析其中的freemarker语法,同时assign的值可以可以互相调用。他可以创建一个命名空间 通过该命名调用import 模板中的变量和宏

 @Testpublic void importFun() throws IOException, TemplateException {Map map = new HashMap();initTemplate("importFun", map);}

import 使用宏

 @Testpublic void macroImportShow() throws IOException, TemplateException {Map map = new HashMap();initTemplate("macroImportShow", map);}

10 freemarker 处理不存在或则为null的值

当数据模型的key不存在或者key 的value是null 时 我们执行模板引擎进行渲染的化或报如下图的错误

我们可以通过在flt页面中使用! 或者 ?if_exists 使其不做任何显示 通过我们也可以通过 ?if_exists 和??指令进行是否为空的判断。

测试模板内容:

${word!}
${word?if_exists}
${product?if_exists.name?if_exists}<#if word??>
<#else>word的值为空
</#if>
<#if word?if_exists>
<#else>word的值为空
</#if>

测试用例:

 @Testpublic void ifExists() throws IOException, TemplateException {Map root = new HashMap();String word = null;root.put("word", word);Product product = new Product();product.setName(null);root.put("product", product);initTemplate("ifExists",root);}

测试结果:

11 freemarker  内置函数

具体请参考:https://freemarker.apache.org/docs/ref_builtins.html

我们这里介绍一下经常使用的内置函数 ,我们上面在介绍list的时候 使用的 ?size就只一个内置函数

11.1字符串

?length :字符串的长度 例如:${"zhuoqianmingyue"?length}

?index_of :字符串中字符的位置交标 例如:${"zhuoqianmingyue"?index_of('yue')}

?substring:截取字符串 例如:${"zhuoqianmingyue"?substring(1)} ${"zhuoqianmingyue"?substring(1,2)}

?trim:去掉字符串的空格 例如:${" Hello world "?trim}

?contains:是否包含否个字符 例如:${"Hello world "?contains('Hello')?string}

?date:日期的转换  ,?datetime datetime的转换

<#assign date1="2009-10-12"?date("yyyy-MM-dd")>
<#assign date2="09:28:20"?datetime("HH:mm:ss")>

?string:字符串格式输出 例如:${date1?string}

?is_string:是否是字符串 例如:${date1?is_string?string}

以上语法模板内容

length: ${"zhuoqianmingyue"?length}
index_of: ${"zhuoqianmingyue"?index_of('yue')}
substring: ${"zhuoqianmingyue"?substring(1)} ${"zhuoqianmingyue"?substring(1,2)}
trim: ${" Hello world "?trim}
contains:${"Hello world "?contains('Hello')?string}<#assign date1="2009-10-12"?date("yyyy-MM-dd")>
<#assign date2="09:28:20"?datetime("HH:mm:ss")>
${date1?is_string?string}
${date1?string}
${date2?string}

测试用例:

 @Testpublic void string() throws IOException, TemplateException {Map map = new HashMap();initTemplate("string", map);}

测试结果:

11.2 日期

.now 获取当前时间

日期格式转换

<#assign aDateTime = .now>
${.now}
${aDateTime?string["dd.MM.yyyy, HH:mm"]}
${aDateTime?string["EEEE, MMMM dd, yyyy, hh:mm a '('zzz')'"]}
${aDateTime?string["EEE, MMM d, ''yy"]}
${aDateTime?string.yyyy}
 @Testpublic void date() throws IOException, TemplateException {Map map = new HashMap();initTemplate("date", map);}

11.3 序列 (Sequence)

?size ?reverse ?sort ?sort_by 我们已经在list 指令进行了演示 这里就不在做介绍了

?chunk:序列分块遍历

?first ?last:获取序列中的第一个和最后一个元素

?join:拼接序列中的内容

?seq_contains:序列中是否包含某个元素

?seq_index_of:序列中元素的交标

<#assign seq = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']><#list seq?chunk(4) as row><#list row as cell>${cell} </#list>
</#list><#list seq?chunk(4, '-') as row><#list row as cell>${cell} </#list>
</#list>
---------------------------------------------${seq[1]} ${seq?first}  ${seq?last} ----------------------------------------------<#assign colors = ["red", "green", "blue"]>${colors?join(", ")}---------------------------------------------
<#assign x = ["red", 16, "blue", "cyan"]>
"blue": ${x?seq_contains("blue")?string("yes", "no")}
"yellow": ${x?seq_contains("yellow")?string("yes", "no")}
16: ${x?seq_contains(16)?string("yes", "no")}
"16": ${x?seq_contains("16")?string("yes", "no")}
-------------------------------------------------
<#assign colors = ["red", "green", "blue"]>
${colors?seq_index_of("blue")}
${colors?seq_index_of("red")}
${colors?seq_index_of("purple")}

测试用例:

 @Testpublic void sequences() throws IOException, TemplateException {Map map = new HashMap();initTemplate("sequences", map);}

11.4 数字:

abs:绝对值    2.3.20

round:四舍五入

floor:向下取整

ceiling:向上取整

string.number:整数数字输出

string.currency:货币格式输出

string.percent:百分数格式输出

?string["0.##"]:数字显示2为小数

?string["000.00"]:小数左面不够0补齐


${-5?abs}
${4.5?round} ${4.4?round}
${4.5?floor} ${4.5?ceiling}<#assign x = 42>
${x}
${x?string}
${x?string.number}
${x?string.currency}
${x?string.percent} ${1.2345?string["0.##"]}
${1.2345?string["000.00"]}
 @Testpublic void number() throws IOException, TemplateException {Map map = new HashMap();initTemplate("number", map);}

11.5 has_api

下面的内置函数返回的结果都是布尔型的

is_string :是否是String

is_number :是否是数字

is_boolean :是否是布尔类型

is_date :是否是日期

is_macro :是否是宏

is_sequence:是否是序列

freemarker Java 模板引擎 基本语法相关推荐

  1. JAVA模板引擎velocity语法讲解

    Velocity 是一个基于 Java 的模板引擎,它允许用户使用简单的模板语言来引用由 Java 代码定义的对象.当 Velocity 应用于 Web 开发时,界面设计人员可以和 Java 程序开发 ...

  2. Java模板引擎 FreeMarker介绍1

    Java模板引擎 FreeMarker介绍 摘要: FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写,FreeMarker被设计用来生成HTML Web页面( ...

  3. Java 模板引擎 ~ FreeMarker。

    Java 模板引擎 ~ FreeMarker. 文章目录 Java 模板引擎 ~ FreeMarker. 数据模型 + 模板 = 输出(HTML). https://freemarker.apache ...

  4. Beetl学习总结(1)——新一代java模板引擎典范 Beetl入门

    1. 什么是Beetl Beetl目前版本是2.7.0,相对于其他java模板引擎,具有功能齐全,语法直观,性能超高,以及编写的模板容易维护等特点.使得开发和维护模板有很好的体验.是新一代的模板引擎. ...

  5. velocity模板引擎-vm语法整理

    velocity模板引擎-vm语法整理 模板引擎我目前接触过两次, 第一次是在前后端还未分离时,考虑到部分页面数据比较固定,一定时间内不会变动,这样每次从后台加载数据渲染页面明显会消耗性能以及资源浪费 ...

  6. Java 模板引擎总结

    Java模板引擎 FreeMarker 概念 介绍 特性 优势 不足 一个小Demo 概念 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写.它是为Java程 ...

  7. java 模板引擎_极简 Spring Boot 整合 Thymeleaf 页面模板

    点击"牧码小子"关注,和众多大牛一起成长! 关注后,后台回复 java ,领取松哥为你精心准备的技术干货! 虽然现在慢慢在流行前后端分离开发,但是据松哥所了解到的,还是有一些公司在 ...

  8. java 模板引擎_SpringBoot入门系列(四)如何整合Thymeleaf模板引擎

    前面介绍了Spring Boot的优点,然后介绍了如何快速创建Spring Boot 项目.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/ ...

  9. java 模板引擎_Spring Boot 如何快熟整合Thymeleaf模板引擎

    前面介绍了Spring Boot的优点,然后介绍了如何快速创建Spring Boot 项目.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/ ...

  10. Thymeleaf学习总结(1)——新一代Java模板引擎Thymeleaf

    Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎.类似JSP,Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用 ...

最新文章

  1. php 更新数据库失败,php 更新数据库中断的解决方法
  2. 沸点压力计算java_java 观察者模式
  3. Google Apps – Framework, Phonesky, GmsCore w/ AOSP Build.
  4. oracle 01192,万分火急:ora-01503 ora-01192
  5. Python dataframe列拆分多行与统计
  6. 恒大俱乐部每年亏损数亿,为何马云还不卖掉手中的股份?
  7. DBGrid 应用系列
  8. matlab 向量法建数组(推荐)
  9. codeforces round #752
  10. 大学的最后一年有一门课程叫“人生”。
  11. 关于母板页中runnat=server 窗体标记的问题
  12. 摄影构图如何脱离规则套路
  13. 【SSM】企业差旅管理系统-李兴华-专题视频课程
  14. 云教室管理平台 部署手册(无图)
  15. 大脑升维:人工智能浪潮下的适者生存之道
  16. 软件著作权个人申请全套攻略
  17. 联想y7000桌面没有计算机,【联想拯救者Y7000P笔记本电脑使用体验】屏幕|键盘_摘要频道_什么值得买...
  18. C语言lowB排序和NB排序
  19. python协程详解
  20. 墨翟科技(上海)有限公司

热门文章

  1. DEM高程数据获取方法
  2. 商务邮箱有哪些?常见邮箱对比
  3. 18项医疗质量安全核心制度
  4. 虚拟机装Win7 x64
  5. 韩国瑜:打造高雄全台首富 3月内完成施政总体检
  6. 超宽带 DWM1000模块 引脚连接
  7. VScode中文注释乱码问题解决
  8. 你是一名技术管理者还是项目管理者?
  9. [路由器] k2p支持ipv6相关设置
  10. Java字符串排序(根据字节及字符长度进行排序)