一、开始
原理图
引入FreeMarker依赖
org.freemarker freemarker 2.3.28
二、入门实例
模板文件: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 创建数据模型 MapdataMap = new HashMap (); 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}
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??> -----------------code<#if users??><#list users as user >${user.id} - ${user.name} <#else>${user!"变量为空则给一个默认值"}
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]} 通过Value遍历Map:<#list mapData?values as value>Value: ${value} List集合:<#assign listData=["ITDragon", "blog", "is", "cool"]><#list listData as value>${value}
3.8 include指令
include指令:引入其他文件:<#include "hello.ftl" />
3.9 宏指令
可以理解为java的封装方法,供其他地方使用。宏指令也称为自定义指令,macro指令语法很简单:<#macro val > 声明macro ; 使用macro <@val />--------------------------codemacro宏指令:<#macro mo>定义无参数的宏macro--${name} 使用宏macro: <@mo /><#macro moArgs a b c>定义带参数的宏macro-- ${a+b+c} 使用带参数的宏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} 内建函数:<#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} <#else>${user!"变量为空则给一个默认值"} Map集合:<#assign mapData={"name":"程序员", "salary":15000}>直接通过Key获取 Value值:${mapData["name"]}通过Key遍历Map:<#list mapData?keys as key>Key: ${key} - Value: ${mapData[key]} 通过Value遍历Map:<#list mapData?values as value>Value: ${value} List集合:<#assign listData=["ITDragon", "blog", "is", "cool"]><#list listData as value>${value} include指令:引入其他文件:<#include "hello.ftl" />macro宏指令:<#macro mo>定义无参数的宏macro--${name} 使用宏macro: <@mo /><#macro moArgs a b c>定义带参数的宏macro-- ${a+b+c} 使用带参数的宏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} <#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() { MapdataMap = new HashMap<>(); dataMap.put("name", "WorldWorld"); dataMap.put("now", new Date()); List 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 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; } }} 代码自动生产程序>