来源:FreeMarker 模板引擎快速入门 与 生成Word文档终极解决方案_freemark word 字体_蚩尤后裔的博客-CSDN博客
1、Apache FreeMarker 是一个模板引擎:一个基于模板和不断变化的数据生成文本输出(HTML网页、电子邮件、配置文件、源代码等)的 Java 库。
2、市面上主流的 Java 模板引擎有:JSP、Velocity、Freemarker、Thymeleaf,Spring Boot 官方支持:Thymeleaf Templates、FreeMarker Templates、Groovy Templates 等模板引擎。
3、虽然 FreeMarker 最初是为在 mvc web 应用程序框架中生成 HTML 页面而创建的,但它并没有绑定到 servlet 或 HTML 或任何与 web 相关的内容,它也用于非 web 应用程序环境。
4、FreeMarker 的一些亮点特性:
1)强大的模板语言:条件块、迭代、赋值、字符串和算术运算和格式化、宏和函数(包括其他模板)、默认转义(可选)等
2)多用途和轻量级:零依赖,任何输出格式,可以从任何地方加载模板(可插拔),许多配置选项
3)国际化/本地化意识:对区域设置敏感的数字和日期/时间格式,本地化的模板变体。
4)XML处理功能:将XMLDOM-s放入数据模型中并遍历它们,甚至以声明方式处理它们
5)多功能数据模型:Java对象通过可插拔适配器作为变量树公开给模板,这决定了模板如何看待它们。
5、参考网址:
Apache FreeMarker 官网地址:https://freemarker.apache.org/、
官方原版英文使用手册:https://freemarker.apache.org/docs/index.html
翻译版中文在线手册:http://freemarker.foofun.cn/index.html
通用目标 | 1、能够生成各种文本:HTML、XML、RTF、Java 源代码等等 2、易于嵌入到产品中:轻量级;不需要 Servlet 环境 3、插件式模板载入器:可以从任何源载入模板,如本地文件、数据库等等 4、可以按所需生成文本:保存到本地文件;作为Email发送;从Web应用程序发送它返回给Web浏览器 |
强大的模板语言 | 1、含有所有常用的指令:include、if/elseif/else、循环结构 2、在模板中创建和改变变量 3、几乎在任何地方都可以使用复杂表达式来指定值 4、命名的宏,可以具有位置参数和嵌套内容 5、名字空间有助于建立和维护可重用的宏库,或者将一个大工程分成模块,而不必担心名字冲突 6、输出转换块:在嵌套模板片段生成输出时,转换HTML转义、压缩、语法高亮等等; |
通用数据模型 | 1、FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在模板中显示 2、可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等等),告诉模板开发者使用方法,使其不受技术细节的打扰 |
智能的国际化和本地化 | 1、字符集智能化(内部使用UNICODE) 2、数字格式本地化敏感 3、日期和时间格式本地化敏感 4、非US字符集可以用作标识(如变量名) 5、多种不同语言的相同模板 |
强大的XML处理能力 | 1、<#recurse> 和<#visit>指令(2.3版本)用于递归遍历XML树 2、在模板中清楚和直觉的访问XML对象模型 |
网页静态化 | 使用如 Freemarker/valocity 技术将动态的页面(jsp,asp.net,php) 转换成静态的页面(如 html),再通过浏览器直接访问静态页面。 浏览器直接访问静态的页面,不需要经过程序处理,访问速度高。 稳定性好。 更有效的防止安全漏洞问题,比如不易遭受黑客攻击。 静态的页面更容易被搜索引擎收录。 |
5、学过 JSP 或者Thymeleaf 任意一种模板引擎的,学习 FreeMarker 就不难,因为语法基本类似,都是使用模板引擎的标签将后台的数据注入到模板中:Template(模板) + data-model(数据模型) = output(静态页面)。
6、相对来说,JSP 和 Thymeleaf 更相似,而 FreeMarker 静态化的模板引擎多一个模板文件,JSP 和 Thymeleaf 都是用户访问后台,然后返回数据,最后直接填充到模板中(JSP或者Html)显示,而 FreeMarker 则必须先使用 Java 代码将数据注入到模板文件中,然后生成静态文件(如 html),最后用户直接访问静态文件。
7、FreeMarker 优点:因为访问的是静态文件,就像访问一个写死的 html 文件一样,它不需要再请求数据库,所以访问速度快;FreeMarker 缺点:缺点也恰恰在此,因为只要数据发生了改变,就必须得重新将新数据注入到模板文件重新生成静态文件,否则用户容易看到过期的数据。
8、个人感受:以后前后端分离才是王道,一是前后端分离后,后台只需要提供接口,不用再写什么模板引擎的标签了,这样前后端只需要调接口即可,对双方无疑都是最好的;二是前端技术日新月异,已经不是很多年前了,展示数据完全没必要再使用 JSP、Thymeleaf 、FreeMarker 这种模板引擎了,前端自己已经有足够优秀的库和框架了。
9、FreeMarker 最常见的用途:一是网页静态化;二是做代码生成,很多代码生成器都是使用的 FreeMarker,先提供模板文件,然后将数据注入进去,最后生成源代码。
1、既然前后端分离才是王道,那模板引擎就不学了吗?这也不绝对,因为像 FreeMarker 除了生成网页,还可以做一些其它操作,比如生成 RFT 办公文档、生成文件作为Email发送、操作 XML 文档等等.
2、本文先一步一步练习 FreeMarker 的标签语法,后面再整合 Spring Boot。本文环境:Java JDK 1.8 + freemarker 2.3.30.
3、导入依赖如下,更多版本以及二进制 Jar 包可以从官网获取。
4、准备 freeMarker 模板文件,官方默认后缀名是 .ftl,理论上任意格式都可以,但是只有 .ftl 格式时,IDEA 才会有 freeMarker 模板标签的语法提示。(模板文件入门示例源码)。
5、使用 FreeMarker 提供 API 将数据模型填充到模板文件中,然后生成静态文件(静态页面生成源码)。
6、下面是演示的动图:
7、freeMarker 的语法相对 JSP 和 Thymeleaf 来说还是有些另类,但好在 IDEA 不用安装插件也能对 .ftl 文件中的 FreeMarker 语法进行提示,下面将平时开发中常见的需求汇总说明如下:
1)freeMarker 控制严格,当操作数据的值为 null 时,生成静态文件时会报错,比如 ${user},如果 user 不存在,或者 user 的值为 null,则生成静态文件时报错。
2)FTL 标记/标签(FreeMarker模板语言标记):类似于 HTML 标记/标签,为了与 HTML 标记区分,用 #或者@ 开始。
3)ftl 注释:包含在 <#-- 和 -->(而不是 )之间,生成的静态文件中是不含这些注释的。
4)ftl 严格区分大小写,如 <#list> 正确,<#LIST> 错误,${name} 和 ${NAME} 结果不一样。
5)ftl 标记不能位于另一个 FTL 标记内部,例如 <#if <#include 'foo'>='bar'>... 是错误的。
6)注释可以位于 FTL 标记和 ${xxx} 内部
7)FreeMarke r会忽略 FTL 标记中的空白字符,但是 "<"、"" 和指令之间不允许有空白字符。
${ key } key 为变量,${ key } 取值后可以直接显示内容,如:${person.pid}、${userName}
${ .now } 获取当前时间
${ key?cap_first } 首字母转大写
${ key?uncap_first } 首字母转小写
${ key?lower_case} 字母全部转小写
${ key?upper_case} 字母全部转大写
${ key.name?length} 获取字符串内容长度
${ key?size} 获取数组、集合的大小,如:${basicList?size}
${ key?replace(String substring,String replacement) } 替换子符串,如 ${personA1.name?replace("MX","猫熊")}
<#if key == "xxx">xxxx#if> 字符串比较与数字比较一样,都是使用 ==,不等于是 != .
<#if key?contains(String substring)>xxxx#if> 判断值是否包含子字符串(substring)
${ key?index_of(String substring)} 获取字符串的索引位置,从0开始
${ key?substring(from)}、${ key?substring(int from,int toExclusive)}
FreeMarker 不会自动进行类型转换,必须手动转换,比如 key 的值是 100001,${ key } 返回的数字,默认会使用千分位符号,所以显示的是 10,001,而 ${ key?c} 转成字符串后,则显示为 100001
${ key?c } 数字类型转字符串类型
${ key?string("currency")} 数字转货币字符串,比如 :9500.11F -> ¥9,500.11
${ key?string("percent")} 数字转百分比,比如:9500.11F -> 9,50011%
${person.birthday?date}
${person.birthday?time}
${person.birthday?datetime}
${person.birthday?string("yyyy/MM/dd HH:mm:ss")}
表示取 yyyy-MM-dd,如 2021-1-2
表示取 HH:mm:ss,如 13:02:45
表示取 yyyy-MM-dd HH:mm:ss,如 2021-1-2 13:03:06
自定义日期格式,如 2021/01/02 13:04:31
${ key?eval } 字符串类型转数字类型,整数浮点数都可以
${ key?number } 字符串类型转数字类型,整数浮点数都可以
<#if key != ""> 判断值是否为空
<#if key??> xxxx #if> 判断值是否为 null 或者 key 不存在,如左侧所示表示当 key 的值不为 null 时,输出 xxxx。
${key!"为null时的默认值"}、${key!""}、${testNull!} 当值为 null 时,可以给出默认值,或者变为空值,!"" 可以省略为 !
<#if key>xxx#if> 布尔值判断,如:<#if person.married>已婚#if>, married 属性是一个 Boolean 类型。
${ key?string(String true,String false)} 如果 key 的结果为 true,则输出 true 的内容,否则输出 false 的内如,如:${p.married?string("是","否")}
${ key[int index]}、${ key[int index].xxx} 获取指定索引位置的元素,如数组、List 等等,例如:${array[0]}、${personList[2].name}
<#if person.salary < 8000>
低产阶级
<#elseif person.salary < 8000>
中产阶级
<#else >
资本家
#if> if 指令:条件判断语句
<#list personList as person>
<#--自定义变量,值有:普通类型、对象类型、接收后台传递的值-->
<#assign toekn="8748378TT8Y66">
<#assign book={"id":"77878TTR55","name":"水浒传","price":89.88}>
算数运算符 FreeMarker 表达式中完全支持算术运算, 包括:+、-、*、/、%
逻辑运算符 &、||、!,逻辑运算符只能作用于布尔值,否则异常
比较运算符
==、!=、> 或者 gt、>= 或者 gte、< 或者 lt、<= 或者 lte
<#if book.price gte 89.88>价格大于60#if>
<#if book.price gte 89.88 && book.name == "水浒传">水浒传价格大于60#if>
1、对于 Word 文档生成/导出功能,虽然 Apache POI 也能做,但是 API 却比较繁琐,所有的格式都需要通过代码来控制,比如字体、颜色、缩进、行距、大小、标题等等,而如果使用 FreeMarker 却非常简单。
2、这得先归功于 Microsoft、WPS、OpenOffice 等办公软件,它们可以将 .doc、.docx 等格式的 Word 文档另存为 .xml 格式,这个 xml 文件里面存储了整个 Word 文档的内容以及格式,如果把 Word 文档比作浏览器中的网页,那么这个 xml 文件就相当于 html 文件。
3、你可以亲自测试一下,将 Word 文档另存为 xml 文件,然后右击保存后的 xml 文件,打开方式仍然选择 Microsoft、WPS、OpenOffice 等办公软件,可以发现和 .doc、docx 等格式完全一样。
4、所以 Java 应用 Word 文档导出终极解决方案如下:
1)先准备一个 .doc、.docx 等格式的 Word 文档模板,后期不变的内容可以直接写死,后期需要变化的内容可以自定义一些占位符先占着位置,比如 #1、#2...,然后设置好文档的格式,比如 字体、颜色、缩进、行距、大小、表格等等。
2)然后将设置好格式的 Word 模板另存为 .xml 文件,使用工具(比如 notepad++ 或者网上的在线格式化工具)对 xml 文件内容进行格式化,然后导入到项目中,并修改后缀名为 .ftl。
3)提供 FreeMarker 模板对应的数据模型,也就是需要往 ftl 文件中注入数据的对象,比如 Map、POJO 等等。
4)然后将 ftl 模板文件中的占位符 #1、#2...使用 FreeMarker 标签进行替换,比如单个值使用 ${xxx} 取值,表格使用 <#list> 遍历等等。
5)最后 Java 后台使用 FreeMarker API 将 .ftl 模板和数据模型生成 .doc 文档。
6)如果是 Web 应用,需要导出文档,则可以将生成好的 .doc 文件使用 javax.servlet.ServletResponse#getWriter 打印流进行输出,让浏览器自动下载。
5、如上所示,使用 FreeMarker 生成 Word 的优点如下:
1)因为模板的格式是提前设置好的,所以生成的 Word 文档完全和事先的预期一模一样。
2)即使是再复杂的格式,只要用户事先能将 Word 文档的格式做得出来,那么 FreeMarker 就能为它注入数据,保证格式一致。
3)Word 另存为 xml 后,后缀改成 ftl 的好处是 IDEA 会有 FreeMarker 语法提示,原则上不改后缀名都是可以的。
4)FreeMarker 根据 xml 生成 .doc 文件和根据 ftl 生成 .html 完全一样的,FreeMarker 标签可以在任意文件中编写,比如 ftl、xml、java、js 等等。
6、涉及到的在线源码如下:
word 源文件以及 .xml 源文件:https://github.com/wangmaoxiong/red-door/tree/master/src/test/resources/word
freeMarker 模板文件:https://github.com/wangmaoxiong/red-door/blob/master/src/test/resources/ftl/purchaseContract.ftl
FreeMarker 后台生成源码:https://github.com/wangmaoxiong/red-door/blob/master/src/test/java/com/wmx/reddoor/freeMarker/PurchaseContract.java
7、此种方式的优点是简单,缺点是只能生成 .doc 格式,无法生成 .docx 格式,如果需要生成 .docx 格式,则操作步骤稍微要多一点点(因为没有需求,所以暂时不讨论)。
————————————————
版权声明:本文为CSDN博主「蚩尤后裔」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wangmx1993328/article/details/111824765