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 快速入门

原文地址:https://www.cnblogs.com/okokabcd/p/8760528.html