FreeMarker速查手册
一、开始
原理图

引入FreeMarker依赖
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
二、入门实例
模板文件:hello.ftl,放到d://tmp/freemark/templates目录下
package ${classPath};
public class ${className} {
public static void main(String[] args) {
System.out.println("${helloWorld}");
}
}
FreemarkerDemo.java
public class FreemarkerDemo {
// 模板路径
private static final String TEMPLATE_PATH = "d://tmp/freemark/templates";
// 生成文件路径
private static final String OUTPUT_PATH = "d://tmp/freemark/output";
public static void main(String[] args) {
// step1 创建freeMarker配置实例
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
Writer out = null;
try {
// step2 获取模版路径
configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
// step3 创建数据模型
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("classPath", "com.freemark.hello");
dataMap.put("className", "AutoCodeDemo");
dataMap.put("helloWorld", "通过简单的 <代码自动生产程序> 演示 FreeMarker的HelloWorld!");
// step4 加载模版文件
Template template = configuration.getTemplate("hello.ftl");
// step5 生成数据
File docFile = new File(OUTPUT_PATH + "\\" + "AutoCodeDemo.java");
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
// step6 输出文件
template.process(dataMap, out);
System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^AutoCodeDemo.java 文件创建成功 !");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != out) {
out.flush();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
执行上面的代码,在d://tmp/freemark/output目录下会生成AutoCodeDemo.java,如下图所示:

三、语法
3.1 数据类型
数据类型
和java不同,FreeMarker不需要定义变量的类型,直接赋值即可。
字符串: value = "xxxx" 。如果有特殊字符 string = r"xxxx" 。单引号和双引号是一样的。
数值:value = 1.2。数值可以直接等于,但是不能用科学计数法。
布尔值:true or false。
List集合:list = [1,2,3] ; list=[1..100] 表示 1 到 100 的集合,反之亦然。
Map集合:map = {"key" : "value" , "key2" : "value2"},key 必须是字符串哦!
实体类:和EL表达式差不多,直接点出来。
3.2 字符串操作
字符串操作:
字符串连接:可以直接嵌套${"hello , ${name}"} ; 也可以用加号${"hello , " + name}
字符串截取:string[index]。index 可以是一个值,也可以是形如 0..2 表示下标从0开始,到下标为2结束。一共是三个数。
-----------------------code
字符串输出:
${"Hello ${name} !"} / ${"Hello " + name + " !"}
<#assign cname=r"特殊字符完成输出(http:\www.baidu.com)">
${cname}
字符串截取 :
通过下标直接获取下标对应的字母: ${name[2]}
起点下标..结尾下标截取字符串:${name[0..5]}
3.3 算术运算符
算数运算:
<#-- 支持"+"、"-"、"*"、"/"、"%"运算符 -->
<#assign number1 = 10>
<#assign number2 = 5>
"+" : ${number1 + number2}
"-" : ${number1 - number2}
"*" : ${number1 * number2}
"/" : ${number1 / number2}
"%" : ${number1 % number2}
3.4 比较运算符
比较运算符:
== (等于),!= (不等于),gt(大于),gte(大于或者等于),lt(小于),lte(小于或者等于)。不建议用 >,< 可能会报错!
一般和 if 配合使用
------------------------------
<#if number1 + number2 gte 12 || number1 - number2 lt 6>
"*" : ${number1 * number2}
<#else>
"/" : ${number1 / number2}
</#if>
3.5 内建函数
内建函数:
FreeMarker 提供了一些内建函数来转换输出,其结构:变量?内建函数,这样就可以通过内建函数来转换输出变量。
html: 对字符串进行HTML编码;
cap_first: 使字符串第一个字母大写;
lower_case: 将字符串转成小写;
upper_case: 将字符串转成大写;
size: 获得集合中元素的个数;
int: 取得数字的整数部分。
--------------------------------
<#assign data = "abcd1234">
第一个字母大写:${data?cap_first}
所有字母小写:${data?lower_case}
所有字母大写:${data?upper_case}
<#assign floatData = 12.34>
数值取整数:${floatData?int}
获取集合的长度:${users?size}
时间格式化:${now?string("yyyy-MM-dd")}
3.6 空判断
变量空判断
! 指定缺失变量的默认值;一般配置变量输出使用
?? 判断变量是否存在。一般配合if使用 <#if value??></#if>
-----------------code
<#if users??>
<#list users as user >
${user.id} - ${user.name}
</#list>
<#else>
${user!"变量为空则给一个默认值"}
</#if>
3.7 list与map
Map集合:
<#assign mapData={"name":"程序员", "salary":15000}>
直接通过Key获取 Value值:${mapData["name"]}
通过Key遍历Map:
<#list mapData?keys as key>
Key: ${key} - Value: ${mapData[key]}
</#list>
通过Value遍历Map:
<#list mapData?values as value>
Value: ${value}
</#list>
List集合:
<#assign listData=["ITDragon", "blog", "is", "cool"]>
<#list listData as value>${value} </#list>
3.8 include指令
include指令:
引入其他文件:<#include "hello.ftl" />
3.9 宏指令
可以理解为java的封装方法,供其他地方使用。宏指令也称为自定义指令,macro指令
语法很简单:<#macro val > 声明macro </#macro>; 使用macro <@val />
--------------------------code
macro宏指令:
<#macro mo>
定义无参数的宏macro--${name}
</#macro>
使用宏macro: <@mo />
<#macro moArgs a b c>
定义带参数的宏macro-- ${a+b+c}
</#macro>
使用带参数的宏macro: <@moArgs a=1 b=2 c=3 />
3.10 命名空间
可以理解为java的import语句,为避免变量重复。一个重要的规则就是:路径不应该包含大写字母,使用下划线_分隔词语,myName --> my_name
语法很简单:<#import "xxx.ftl" as val>
---------------------code
命名空间:
<#import "otherFreeMarker.ftl" as otherFtl>
${otherFtl.otherName}
<@otherFtl.addMethod a=10 b=20 />
<#assign otherName="修改otherFreeMarker.ftl中的otherName变量值"/>
${otherFtl.otherName}
<#assign otherName="修改otherFreeMarker.ftl中的otherName变量值" in otherFtl />
${otherFtl.otherName}
四、汇总实例
learn.ftl
字符串输出:
${"Hello ${name} !"} / ${"Hello " + name + " !"}
<#assign cname=r"特殊字符完成输出(http:\www.baidu.com)">
${cname}
字符串截取 :
通过下标直接获取下标对应的字母: ${name[2]}
起点下标..结尾下标截取字符串:${name[0..5]}
算数运算:
<#-- 支持"+"、"-"、"*"、"/"、"%"运算符 -->
<#assign number1 = 10>
<#assign number2 = 5>
"+" : ${number1 + number2}
"-" : ${number1 - number2}
"*" : ${number1 * number2}
"/" : ${number1 / number2}
"%" : ${number1 % number2}
比较运算符:
<#if number1 + number2 gte 12 || number1 - number2 lt 6>
"*" : ${number1 * number2}
<#else>
"/" : ${number1 / number2}
</#if>
内建函数:
<#assign data = "abcd1234">
第一个字母大写:${data?cap_first}
所有字母小写:${data?lower_case}
所有字母大写:${data?upper_case}
<#assign floatData = 12.34>
数值取整数:${floatData?int}
获取集合的长度:${users?size}
时间格式化:${now?string("yyyy-MM-dd")}
空判断和对象集合:
<#if users??>
<#list users as user >
${user.id} - ${user.name}
</#list>
<#else>
${user!"变量为空则给一个默认值"}
</#if>
Map集合:
<#assign mapData={"name":"程序员", "salary":15000}>
直接通过Key获取 Value值:${mapData["name"]}
通过Key遍历Map:
<#list mapData?keys as key>
Key: ${key} - Value: ${mapData[key]}
</#list>
通过Value遍历Map:
<#list mapData?values as value>
Value: ${value}
</#list>
List集合:
<#assign listData=["ITDragon", "blog", "is", "cool"]>
<#list listData as value>${value} </#list>
include指令:
引入其他文件:<#include "hello.ftl" />
macro宏指令:
<#macro mo>
定义无参数的宏macro--${name}
</#macro>
使用宏macro: <@mo />
<#macro moArgs a b c>
定义带参数的宏macro-- ${a+b+c}
</#macro>
使用带参数的宏macro: <@moArgs a=1 b=2 c=3 />
命名空间:
<#import "otherFreeMarker.ftl" as otherFtl>
${otherFtl.otherName}
<@otherFtl.addMethod a=10 b=20 />
<#assign otherName="修改otherFreeMarker.ftl中的otherName变量值"/>
${otherFtl.otherName}
<#assign otherName="修改otherFreeMarker.ftl中的otherName变量值" in otherFtl />
${otherFtl.otherName}
otherFreeMarker.ftl
其他FreeMarker文件
<#macro addMethod a b >
result : ${a + b}
</#macro>
<#assign otherName="另外一个FreeMarker的变量">
测试类:FreeMarkerTest.java
public class FreemarkerTest {
// 模板目录
private static final String TEMPLATE_PATH = "d://tmp/freemark/templates";
// 输出目录
private static final String OUTPUT_PATH = "d://tmp/freemark/output";
@Test
public void test001() {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("name", "WorldWorld");
dataMap.put("now", new Date());
List<User> users = new ArrayList<>();
for (int i=0; i<19; i++) {
users.add(new User(i, "name" + i));
}
dataMap.put("users", users);
// hello.ftl中用到的数据
dataMap.put("classPath", "com.freemark.hello");
dataMap.put("className", "AutoCodeDemo");
dataMap.put("helloWorld", "通过简单的 <代码自动生产程序> 演示 FreeMarker的HelloWorld!");
dataMap.put("otherName", "这是otherName");
testFreemarker("learn.ftl", dataMap, "learn.txt");
}
public void testFreemarker(String templateName, Map<String, Object> dataMap, String outputName) {
// step1 创建freeMarker配置实例
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
Writer out = null;
try {
// step2 获取模版路径
configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
// step3 创建数据模型
// step4 加载模版文件
Template template = configuration.getTemplate(templateName);
// step5 生成数据
File docFile = new File(OUTPUT_PATH + "\\" + outputName);
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
// step6 输出文件
template.process(dataMap, out);
System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^" + outputName + " 文件创建成功 !");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != out) {
out.flush();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
public class User {
private Integer id;
private String name;
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
五、参考
FreeMarker速查手册的更多相关文章
- 《zw版·Halcon-delphi系列原创教程》 zw版-Halcon常用函数Top100中文速查手册
<zw版·Halcon-delphi系列原创教程> zw版-Halcon常用函数Top100中文速查手册 Halcon函数库非常庞大,v11版有1900多个算子(函数). 这个Top版,对 ...
- 25个有用的和方便的 WordPress 速查手册
如果你是 WordPress 开发人员,下载一些方便的 WordPress 备忘单可以在你需要的时候快速查找.下面这个列表,我们已经列出了25个有用的和方便的 WordPress 速查手册,赶紧收藏吧 ...
- R之data.table速查手册
R语言data.table速查手册 介绍 R中的data.table包提供了一个data.frame的高级版本,让你的程序做数据整型的运算速度大大的增加.data.table已经在金融,基因工程学等领 ...
- 25个有用和方便的 WordPress 速查手册
如果你是一个 WordPress 编码器或开发人员,下载一些方便的 WordPress 备忘单寻找你的工作然后你在正确的地方.我们已经列出了25个有用的和方便的 WordPress 速查手册.Word ...
- 几个较好的SQL速查手册网址
微软 SQL server 数据库开发手册 数据库设计 Transact-SQL 速查手册 数据库设计 MySQL 中文参考手册速查 结构化查询语言 SQL 学习手册速查 转自:http://www. ...
- web 开发:CSS3 常用属性——速查手册!
web 开发:CSS3 常用属性——速查手册! CSS3 简介:http://www.runoob.com/css3/css3-intro.html 1.目录 http://caniuse.com/ ...
- Markdown速查手册
之前一直使用简书做笔记,沉浸式的写作环境很棒.然而不知什么时候起,氛围愈发浮躁,软文鸡汤泛滥,离"简"字越来越远. 相比更加喜欢沉稳低调.内涵取胜的博客园.于是乎搬家! 搬家就要丢 ...
- Pandas速查手册中文版
本文翻译自文章: Pandas Cheat Sheet - Python for Data Science ,同时添加了部分注解. 对于数据科学家,无论是数据分析还是数据挖掘来说,Pandas是一个非 ...
- SSM 项目从搭建爬坑到 CentOS 服务器部署 - 速查手册
SSM 项目从搭建爬坑到 CentOS 服务器部署 - 速查手册 提示: (1)CSDN 博客左边有操作工具条上有文章目录 (2)SSM 指 Spring,Spring MVC,MyBatis Mav ...
随机推荐
- Azure DevOps 中 Dapr项目自动部署流程实践
注:本文中主要讨论 .NET6.0项目在 k8s 中运行的 Dapr 的持续集成流程, 但实际上不是Dapr的项目部署到K8s也是相同流程,只是k8s的yaml配置文件有所不同 流程选择 基于 Dap ...
- html dom 转化成图片踩坑记(canvas toDataURL)
需求 在开发过程中遇到这么一个需求,h5页面需要将一个html dom转化成图片,便于用户保存. 面向百度搜索第三方得 html2canvas 和 dom-to-image 两者在写这篇笔记之前在gi ...
- PAT B1056组合数的和
给定 N 个非 0 的个位数字,用其中任意 2 个数字都可以组合成 1 个 2 位的数字.要求所有可能组合出来的 2 位数字的和.例如给定 2.5.8,则可以组合出:25.28.52.58.82.85 ...
- JavaScript操作checkbox复选框
运行效果: 源代码: 1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta char ...
- 多条命令同时执行的包concurrently
npm i concurrently use "script":{ "client:build": "webpack --config build/w ...
- Wireshark-过滤器-数据包解析
目录 过滤器 数据包解析 参考 推荐阅读: https://www.cnblogs.com/zwtblog/tag/计算机网络/ 过滤器 显示过滤器 和 捕获过滤器,俩者使用非常类似. 在Wiresh ...
- Python接口自动化——文件上传/下载接口
〇.前言 文件上传/下载接口与普通接口类似,但是有细微的区别. 如果需要发送文件到服务器,例如:上传文档.图片.视频等,就需要发送二进制数据,上传文件一般使用的都是 Content-Type: mul ...
- Android搞定权限申请
0x00 前言 使用EasyPermissions库进行申请权限 打开App时就申请权限,如果用户拒绝权限后,会循环申请 如果永久拒绝后,会跳转到设置里继续申请 效果图: 注:不讲原理,先教你怎么实现 ...
- Metaspaloit漏洞利用
Metaspaloit介绍Metaspaloit介绍 Metasploit是一款开源的安全漏洞检测工具,可以帮助安全和IT专业人士识别安全性问题,验证漏洞的缓解措施,并管理专家驱动的安全性进行评估,提 ...
- 2021.08.16 P1300 城市街道交通费系统(dfs)
2021.08.16 P1300 城市街道交通费系统(dfs) P1300 城市街道交通费系统 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 城市街道交费系统最近创立了.一 ...