FreeMarker 快速入门
FreeMarker是一个很值得去学习的模版引擎。它是基于模板文件生成其他文本的通用工具。本章内容通过如何使用FreeMarker生成Html web 页面 和 代码自动生成工具来快速了解FreeMarker。
1 简介
FreeMarker是一款用java语言编写的模版引擎,它虽然不是web应用框架,但它很合适作为web应用框架的一个组件。
特点:
1. 轻量级模版引擎,不需要Servlet环境就可以很轻松的嵌入到应用程序中
2. 能生成各种文本,如html,xml,java,等
3. 入门简单,它是用java编写的,很多语法和java相似
工作原理:(借用网上的图片)
2 FreeMarker 程序
这里通过模拟简单的代码自动生产工具来感受第一个FreeMarker程序。
项目目录结构
项目创建流程
第一步:创建一个maven项目导入 FreeMarker jar 包
第二步:创建目录templates,并创建一个 FreeMarker模版文件 hello.ftl
第三步:创建一个运行FreeMarker模版引擎的 FreeMarkerDemo.java 文件
第四步:运行main方法后刷新项目
pom.xml 文件 ,maven 项目核心文件,管理 jar 包。
13 4.0.0 4com.freemark 5freemarkerStudy 60.0.1-SNAPSHOT 7war 8 910 16 1711 15org.freemarker 12freemarker 132.3.20 14
hello.ftl FreeMarker基本语法: ${xxx} xxx 相当于占位符,java后台给xxx赋值后,再通过${}输出
1 package ${classPath};2 3 public class ${className} {4 5 public static void main(String[] args) {6 System.out.println("${helloWorld}");7 }8 9 }
FreeMarkerDemo.java 核心方法,使用 FreeMarker 模版引擎。
1 package com.freemark.hello; 2 3 import java.io.BufferedWriter; 4 import java.io.File; 5 import java.io.FileOutputStream; 6 import java.io.OutputStreamWriter; 7 import java.io.Writer; 8 import java.util.HashMap; 9 import java.util.Map;10 11 import freemarker.template.Configuration;12 import freemarker.template.Template;13 14 /**15 * 最常见的问题: 16 * java.io.FileNotFoundException: xxx does not exist. 解决方法:要有耐心17 * FreeMarker jar 最新的版本(2.3.23)提示 Configuration 方法被弃用18 * 代码自动生产基本原理:19 * 数据填充 freeMarker 占位符20 */21 public class FreemarkerDemo {22 23 private static final String TEMPLATE_PATH = "src/main/java/com/freemark/hello/templates";24 private static final String CLASS_PATH = "src/main/java/com/freemark/hello";25 26 public static void main(String[] args) {27 // step1 创建freeMarker配置实例28 Configuration configuration = new Configuration();29 Writer out = null;30 try {31 // step2 获取模版路径32 configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));33 // step3 创建数据模型34 MapdataMap = new HashMap ();35 dataMap.put("classPath", "com.freemark.hello");36 dataMap.put("className", "AutoCodeDemo");37 dataMap.put("helloWorld", "通过简单的 <代码自动生产程序> 演示 FreeMarker的HelloWorld!");38 // step4 加载模版文件39 Template template = configuration.getTemplate("hello.ftl");40 // step5 生成数据41 File docFile = new File(CLASS_PATH + "\\" + "AutoCodeDemo.java");42 out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));43 // step6 输出文件44 template.process(dataMap, out);45 System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^AutoCodeDemo.java 文件创建成功 !");46 } catch (Exception e) {47 e.printStackTrace();48 } finally {49 try {50 if (null != out) {51 out.flush();52 }53 } catch (Exception e2) {54 e2.printStackTrace();55 }56 }57 }58 59 } 代码自动生产程序>
运行程序后刷新项目,会发现多了一个AutoCodeDemo.java类。不仅仅是java类,xml也是可以。笔者就是通过FreeMarker做了一个简易的工具类,公司的一个标准管理页面及其增删改查等功能,以及相关的配置文件(十三个文件),一个回车就全部自动生成(偷懒ing)。
3 FreeMarker 语法
语法和java很类似,其中宏的概念可能比较陌生,先上代码
stringFreeMarker.ftl FreeMarker主要核心知识点
字符串输出:${"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}时间格式化:${dateTime?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 "otherFreeMarker.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 为了测试命名空间 和 include 指令的FreeMarker文件
其他FreeMarker文件<#macro addMethod a b >result : ${a + b} <#assign otherName="另外一个FreeMarker的变量">
FreeMarkerDemo.java 核心方法
1 package com.freemark.demo; 2 3 import java.util.List; 4 import java.io.BufferedWriter; 5 import java.io.File; 6 import java.io.FileOutputStream; 7 import java.io.OutputStreamWriter; 8 import java.io.Writer; 9 import java.util.Date;10 import java.util.ArrayList;11 import java.util.HashMap;12 import java.util.Map;13 14 import freemarker.template.Configuration;15 import freemarker.template.Template;16 17 public class FreeMarkerDemo {18 19 private static final String TEMPLATE_PATH = "src/main/java/com/freemark/demo/templates";20 21 public static void main(String[] args) {22 // step1 创建freeMarker配置实例23 Configuration configuration = new Configuration();24 Writer out = null;25 try {26 // step2 获取模版路径27 configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));28 // step3 创建数据模型29 MapdataMap = new HashMap ();30 dataMap.put("name", "itdragon博客");31 dataMap.put("dateTime", new Date());32 33 List users = new ArrayList ();34 users.add(new User(1, "ITDragon 博客"));35 users.add(new User(2, "欢迎"));36 users.add(new User(3, "You!"));37 dataMap.put("users", users);38 // step4 加载模版文件39 Template template = configuration.getTemplate("stringFreeMarker.ftl");40 // step5 生成数据41 out = new OutputStreamWriter(System.out);42 // step6 输出文件43 template.process(dataMap, out);44 } catch (Exception e) {45 e.printStackTrace();46 } finally {47 try {48 if (null != out) {49 out.flush();50 }51 } catch (Exception e2) {52 e2.printStackTrace();53 }54 }55 }56 57 }
User.java 为了测试 FreeMarker的集合对象
1 package com.freemark.demo; 2 3 public class User { 4 5 private Integer id; 6 private String name; 7 8 public User() { 9 }10 11 public User(Integer id, String name) {12 this.id = id;13 this.name = name;14 }15 16 public Integer getId() {17 return id;18 }19 20 public void setId(Integer id) {21 this.id = id;22 }23 24 public String getName() {25 return name;26 }27 28 public void setName(String name) {29 this.name = name;30 }31 32 @Override33 public String toString() {34 return "User [id=" + id + ", name=" + name + "]";35 }36 37 }
最后的打印结果
字符串输出:Hello itdragon博客 ! / Hello itdragon博客 !特殊字符完成输出(http:\www.baidu.com)字符串截取 : 通过下标直接获取下标对应的字母: d起点下标..结尾下标截取字符串:itdrag算数运算:"+" : 15"-" : 5"*" : 50"/" : 2"%" : 0比较运算符:"*" : 50内建函数:第一个字母大写:Abcd1234所有字母小写:abcd1234所有字母大写:ABCD1234数值取整数:12获取集合的长度:3时间格式化:2017-10-29空判断和对象集合:1 - ITDragon 博客2 - 欢迎3 - You!Map集合:直接通过Key获取 Value值:程序员通过Key遍历Map:Key: name - Value: 程序员Key: salary - Value: 15,000通过Value遍历Map:Value: 程序员Value: 15,000List集合:ITDragon blog is cool include指令:其他FreeMarker文件macro宏指令:使用宏macro: 定义无参数的宏macro--itdragon博客使用带参数的宏macro: 定义带参数的宏macro-- 6命名空间:另外一个FreeMarker的变量result : 30另外一个FreeMarker的变量修改otherFreeMarker.ftl中的otherName变量值
语法详解
数据类型
和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表达式差不多,直接点出来。
字符串操作
字符串连接:可以直接嵌套${"hello , ${name}"} ; 也可以用加号${"hello , " + name}
字符串截取:string[index]。index 可以是一个值,也可以是形如 0..2 表示下标从0开始,到下标为2结束。一共是三个数。
比较运算符
== (等于),!= (不等于),gt(大于),gte(大于或者等于),lt(小于),lte(小于或者等于)。不建议用 >,< 可能会报错!
一般和 if 配合使用
内建函数
FreeMarker 提供了一些内建函数来转换输出,其结构:变量?内建函数,这样就可以通过内建函数来转换输出变量。
1. html: 对字符串进行HTML编码;
2. cap_first: 使字符串第一个字母大写;3. lower_case: 将字符串转成小写;4. upper_case: 将字符串转成大写;5. size: 获得集合中元素的个数;6. int: 取得数字的整数部分。变量空判断
! 指定缺失变量的默认值;一般配置变量输出使用
?? 判断变量是否存在。一般配合if使用 <#if value??></#if>宏指令
可以理解为java的封装方法,供其他地方使用。宏指令也称为自定义指令,macro指令
语法很简单:<#macro val > 声明macro </#macro>; 使用macro <@val />
命名空间
可以理解为java的import语句,为避免变量重复。一个重要的规则就是:路径不应该包含大写字母,使用下划线_分隔词语,myName --> my_name
语法很简单:<#import "xxx.ftl" as val>
其他没有说明的语法是因为和java一样,没什么特别之处。所以没有列出来。
4 FreeMarker Web
这里是和SpringMVC整合的,SpringMVC的配置就不多说了,笔者也写过相关的文章,同时也会提供源码
导入相关的jar pom.xml
org.freemarker freemarker 2.3.20 org.springframework spring-context-support 4.1.4.RELEASE
springmvc的配置文件:
Controller 层
import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class HelloFreeMarkerController { @RequestMapping("/helloFreeMarker") public String helloFreeMarker(Model model) { model.addAttribute("name","ITDragon博客"); return "helloFreeMarker"; }}
最后是Freemarker文件
FreeMarker Web Hello ${name} !
源码地址:
5 小结
1. 知道了FreeMarker是一块模版引擎,可以生产xml,html,java等文件
2. 知道了FreeMarker文件提供占位符,java文件提供数据,通过FreeMarker模版引擎生产有数据的页面,文中是将数据放在Map中。web应用可以用setter/getter 方法
3. 知道了FreeMarker语法中字符串的显示特殊字符,截取的操作。以及一些内置方法的使用
4. 重点了解FreeMarker的空判断知识点。判断变量是否为空用 "??" ,如果变量为空设置默认值。如果不注意空问题,可能会出现黄色页面的提示哦!
5. FreeMarker的宏概念,命名空间,引入文件,给变量赋值,集合的遍历等。
6. Freemarker 整合SpringMVC。
到这里FreeMarker的入门就结束了,是不是很简单。如果有什么不对的地方,请指正!