FreeMarker Basic

1.Introduction

visit http://freemarker.sourceforge.net/ for more information.

 

2.Maven Dependency

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>org.fool.freemarker</groupId>
	<artifactId>freemarker</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>freemarker</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>2.3.19</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

 

3.Project Directory

FreeMarker Basic_第1张图片
 

4.FreemarkerUtil

package org.fool.freemarker.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class FreemarkerUtil
{
	public Template getTemplate(String name)
	{
		Template template = null;

		try
		{
			// 通过Freemaker的Configuration读取相应的ftl
			Configuration cfg = new Configuration();

			// 设定去哪里读取相应的ftl模板文件
			cfg.setClassForTemplateLoading(this.getClass(), "/ftl");

			// 在模板文件目录中找到名称为name的文件
			template = cfg.getTemplate(name);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

		return template;
	}

	public void print(String name, Map<String, Object> root)
	{
		try
		{
			// 通过Template可以将模板文件输出到相应的流
			Template template = this.getTemplate(name);
			template.process(root, new PrintWriter(System.out));
		}
		catch (TemplateException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	public void fprint(String name, Map<String, Object> root, String outFile)
	{
		FileWriter out = null;

		try
		{
			out = new FileWriter(new File(outFile));
			Template template = this.getTemplate(name);
			template.process(root, out);
			out.flush();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		catch (TemplateException e)
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				if (out != null)
				{
					out.close();
				}
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
	}
}

 

5.基本使用

User.java

package org.fool.freemarker.model;

public class User
{
	private int id;
	private String name;
	private int age;

	private Group group;

	public User()
	{
	}

	public User(int id, String name, int age)
	{
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public int getId()
	{
		return id;
	}

	public void setId(int id)
	{
		this.id = id;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public int getAge()
	{
		return age;
	}

	public void setAge(int age)
	{
		this.age = age;
	}

	public Group getGroup()
	{
		return group;
	}

	public void setGroup(Group group)
	{
		this.group = group;
	}

}

Group.java

package org.fool.freemarker.model;

public class Group
{
	private String name;

	public Group()
	{
	}

	public Group(String name)
	{
		this.name = name;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

}

Student.java

package org.fool.freemarker.model;

public class Student
{
	private String no;
	private String name;

	public Student()
	{
	}

	public Student(String no, String name)
	{
		this.no = no;
		this.name = name;
	}

	public String getNo()
	{
		return no;
	}

	public void setNo(String no)
	{
		this.no = no;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

}

Article.java

package org.fool.freemarker.model;

public class Article
{
	private String title;
	private Channel channel;

	public Article()
	{
	}

	public Article(String title, Channel channel)
	{
		this.title = title;
		this.channel = channel;
	}

	public String getTitle()
	{
		return title;
	}

	public void setTitle(String title)
	{
		this.title = title;
	}

	public Channel getChannel()
	{
		return channel;
	}

	public void setChannel(Channel channel)
	{
		this.channel = channel;
	}

}

Channel.java

package org.fool.freemarker.model;

public class Channel
{
	private int id;
	private String name;

	public Channel(int id, String name)
	{
		this.id = id;
		this.name = name;
	}

	public Channel()
	{
	}

	public int getId()
	{
		return id;
	}

	public void setId(int id)
	{
		this.id = id;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

}

  

 

TestFreemarker.java

package org.fool.freemarker.test;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.fool.freemarker.model.Article;
import org.fool.freemarker.model.Channel;
import org.fool.freemarker.model.Student;
import org.fool.freemarker.model.User;
import org.fool.freemarker.util.FreemarkerUtil;
import org.junit.Before;
import org.junit.Test;

public class TestFreemarker
{
	FreemarkerUtil fu = null;

	// 创建数据模型
	Map<String, Object> root = null;

	@Before
	public void setUp()
	{
		fu = new FreemarkerUtil();
		root = new HashMap<>();
	}

	@Test
	public void test0102()
	{
		// 为数据模型添加值
		root.put("username", "Hero");

		// 将数据模型和模板组合的数据输出到控制台
		fu.print("01.ftl", root);
		fu.fprint("02.ftl", root, "01.html");
	}

	@Test
	public void test03()
	{
		root.put("user", new User(1, "Hero", 16));
		sprint("03.ftl");
		fprint("03.ftl", "03.html");
	}

	@Test
	public void test04()
	{
		List<User> users = Arrays.asList(new User(1, "Hero", 16), new User(1,
				"Heroine", 18));

		root.put("users", users);
		sprint("04.ftl");
		fprint("04.ftl", "04.html");
	}

	@Test
	public void test05()
	{
		List<User> users = Arrays.asList(new User(1, "Hero", 16), new User(1,
				"Heroine", 18));
		root.put("username", "admin");
		root.put("users", users);
		sprint("05.ftl");
		fprint("05.ftl", "05.html");
	}

	@Test
	public void test06()
	{
		// 此时user对象并没有group的值,这时如果在页面显示group直接报错
		// freemarker不会处理空值
		root.put("user", new User(1, "Hero", 16));
		sprint("06.ftl");
		fprint("06.ftl", "06.html");
	}

	@Test
	public void test07()
	{
		root.put("now", new Date());
		root.put("username", "Hero");
		sprint("07.ftl");
		fprint("07.ftl", "07.html");
	}

	@Test
	public void test08()
	{
		sprint("08.ftl");
	}

	@Test
	public void test09()
	{
		sprint("09.ftl");
	}

	@Test
	public void test10()
	{
		root.put("username", "Hero");
		sprint("10.ftl");
	}

	@Test
	public void test11()
	{
		sprint("11.ftl");
	}

	@Test
	public void test12()
	{
		List<User> users = Arrays.asList(new User(1, "Hero", 22), new User(2,
				"Heroine", 33), new User(3, "HeroAndHeroine", 44));
		root.put("users", users);
		List<Student> stus = Arrays.asList(new Student("12345", "Puck"),
				new Student("67890", "Doom"));
		root.put("stus", stus);
		sprint("12.ftl");
		fprint("12.ftl", "12.html");
	}

	@Test
	public void test13()
	{
		sprint("13.ftl");
		fprint("13.ftl", "13.html");
	}

	@Test
	public void test14()
	{
		Map<String, List<Article>> arts = new HashMap<String, List<Article>>();
		List<Article> a1 = Arrays.asList(
				new Article("哈登上星!不是东道主也够格! 休城四年后再出明星", new Channel(1, "All Star")), 
				new Article("ESPN新星榜哈登高居第4 最像希尔未来赶超滑翔机?", new Channel(1, "All Star")),
				new Article("哈登入选全明星实至名归 高富帅有望亮相新秀挑战赛", new Channel(1, "All Star")), 
				new Article("诺天王连续11年全明星纪录终止 季后赛成首要目标", new Channel(1, "All Star")), 
				new Article("欧文小霍首次入选接控卫大旗 两王牌后卫遗憾落选", new Channel(1, "All Star")), 
				new Article("巴克利炮轰全明星替补名单:库里没进头要气炸了!", new Channel(1, "All Star")));
		

		List<Article> a2 = Arrays.asList(
				new Article("魔兽右肩复查伤情无大碍 明天主场战爵士继续出战", new Channel(1, "LAL")), 
				new Article("湖人5大悲催看点:科比数据年≠成功 四巨头瓦解?", new Channel(1, "LAL")), 
				new Article("湖人名宿气炸:这队正走向灾难 死了!死了!都死了!", new Channel(1, "LAL")),
				new Article("湖人会议科比质问魔兽", new Channel(1, "LAL")),
				new Article("勇士主帅为库里落选鸣冤!:魔兽?他入选就是笑话", new Channel(1, "LAL")), 
				new Article("湖人要哭的在后头 5连败打雷霆?还记得宝强那张神图", new Channel(1, "LAL")));
		
		arts.put("1", a1);
		arts.put("2", a2);
		root.put("arts", arts);
		
		sprint("14.ftl");
		fprint("14.ftl", "14.html");
	}

	private void sprint(String name)
	{
		fu.print(name, root);
	}

	private void fprint(String name, String filename)
	{
		fu.fprint(name, root, filename);
	}
}

 

将文件读写到html中

01.ftl

Hello:${username}

02.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>${username}</h1>
</body>
</html>

  

常用指令

03.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>${user.id}-----${user.name}-----${user.age}</h1>
<#if user.age lt 12>
	${user.name} is a teenager
<#elseif user.age lt 18>
	${user.name} is almost an adult
<#else>
	${user.name} is an adult
</#if>
</body>
</html>

04.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#list users as user>
${user.id}---------${user.name}-------${user.age}<br/>
</#list>
</body>
</html>

05.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#include "/inc/top.ftl">
<hr>
<#list users as user>
${user.id}---------${user.name}-------${user.age}<br>
</#list>
</body>
</html>

 top.ftl

<h1>Welcome ${username}</h1>

 

空值的处理

06.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
${user.id}---------${user.name}-------${user.group!}<br>
<#-- ${user.group.name!} -->
<#-- 按照以上的方式加! freemarker仅仅只会判断group.name是不是空值 -->
${(user.group.name)!"没有任何值存在"}

${(a.b)!"没有a.b元素"}
<#if (a.b)??>
	不为空
<#else>
	为空
</#if>
</body>
</html>

 

基本数据类型

07.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#--定义变量-->
<#assign username="Heroine" />
${username}
<#--定义了一个数字-->
<#assign num=10 />
${num+11}
<#assign str="10" />
${str+11}
<#--值会完成覆盖-->
<#assign str="33" />
${str+11}
<#assign b=true/>
<#--不能直接输出数字或者字符串以外的类型,否则都会报错,需要转换为字符串才能输出
	使用xxx?string可以完成对字符串的转换
-->
<#--${b}-->
${b?string}
${(a.d)???string}
<#--日期也不能直接输出,需要转换为字符串-->
${now?string("yyyy-MM-dd HH:mm:ss")}
<#--${now?string}没有为日期设定格式也会报错-->

<#--以下显示了使用字符链接和插值的方式连接字符串-->
${"hello "+username}

${"hello ${username}"}

<#--字符串转换为日期
date用来转换日期,datetime用来转换日期和时间,time用来转换时间
-->
<#assign bir1="2012-12-21 12:22:33"?date("yyyy-MM-dd HH:mm:ss") />
<#assign bir2="2000-01-01 12:22:33"?datetime("yyyy-MM-dd HH:mm:ss") />
${bir1}
${bir2}

${"<br>"?html}

[${"abcde"?left_pad(10,"--")}]

${1.4?string(0)}
${1.8?int}
</body>
</html>

 

序列和哈希表

08.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#assign nums=[1,3,4,56,33,43] />
${nums?first}
<#--特别注意,以下定义不使用[12..200]-->
<#assign nums=12..200 /><#--定义了一个连续的序列从12到199-->
<#--序列的拆分-->
<#assign nums1=nums[1..10] />
<#list nums1 as num>
${num}
</#list>
${"你好,你来了吗今天看书了吗!"[0..8]}...
<#assign maps={"1":"Hero", "2":"Heroine"} />
${maps["1"]}
<#--以下代码可以将map的key转换为相应的序列-->
<#assign keys=maps?keys />
<#list keys as key>
${key}---${maps[key]}

<#assign users={"username":"Hero","password":"123"} />
${users.username}---${users["password"]}
</#list>
</body>
</html>

 

自定义指令

09.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#--对于hello这个自定义指令而言,hello后的都是参数,有两个参数一个是num一个是ok-->
<#macro hello num ok>
	<#list 1..num as n>
	<h1>Hello${ok}${n}</h1>
	</#list>
</#macro>

<#--<@hello/>会报错,因为hello有两个参数,在定义参数的值的时候参数名不能省略-->
<@hello num=3 ok="World"/>

<#--为repeat的两个参数定义了初始值,此时在调用该指令就可以省略参数,如果省略会使用默认值-->
<#macro repeat num=10 ok="World">
	<#list 1..num as n>
	<h1>Hello${ok}${n}</h1>
	</#list>
</#macro>

<@repeat/>

<#macro test>
	<#--nested会输出指令中的内容-->
	<#nested 12 33/>
	<#nested 11 22/>
	<#nested 22 33/>
</#macro>

<@test;x,y>
	<h1>你好啊--${x}--${y}</h1>
</@test>
</body>
</html>

10.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#--此时模板中的变量的名称和模型中的变量名称一致,不是覆盖,而是隐藏-->
<#assign username="Heroine" />
${username}
<#--使用.globals可以访问模型中的变量-->
${.globals.username}
<#macro test>
	<#--此时当调用该指令之后,会将模板中的变量username覆盖为王五
	所以这种方式存在风险,所以一般不使用这种方式在指令中定义变量-->
	<#--<#assign username="HeroAndHeroine">-->
	<#--使用local可以声明局部变量,所以在marco中非特殊使用局部变量-->
	<#local username="HeroAndHeroine">
	${username}
</#macro>
<@test/>
${username}

<#list 1..3 as username>
	<#--循环中的变量出了循环就消失-->
	${username}
</#list>

${username}
</body>
</html>

 

11.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#--
	使用incldue可能会出现覆盖的问题,可以使用import来完成导入,并且加入名称空间
	<#include "/inc/inc1.ftl"/>
	<#include "/inc/inc2.ftl"/>
-->
<#import "/inc/inc1.ftl" as inc1 />
<#import "/inc/inc2.ftl" as inc2 />
${inc1.username}
${inc2.username}

<#--将一个变量定义到名称空间中-->
<#assign age=12 in inc2 />
${inc2.age}

<#--访问名称空间中的自定义指令-->
<@inc1.test />
</body>
</html>

inc1.ftl

<#assign username="Hero">

<#macro test>
	hello world
</#macro>

inc2.ftl

<#assign username="Heroine">

 

实现通用select

12.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#import "/inc/select.ftl" as my/>
<@my.select id="address" datas=["北京","天津","上海"]/>
<@my.select id="sex" datas=["选择性别","男","女"] value="男"/>
<@my.select id="username" datas=users key="id" text="name" 
		headkey="-1" headtext="请选择用户"/>

<@my.select id="stu" datas=stus key="no" text="name" 
		headkey="-1" headtext="请选择学生"/>

<@my.select id="sex" datas={"0":"男","1":"女"} value="1"/>
</body>
</html>

select.ftl

<#macro select id datas value="" key="" text="" headkey="" headtext="">
	<select id="${id}" name="${id}">
	<#if headkey!="">
	<option value="${headkey}">${headtext}</option>
	</#if>
	<#if datas?is_hash_ex>
	<#local keys=datas?keys/>
	<#list keys as key>
		<#if key==value>
			<option value="${key}" selected="selected">${datas[key]}</option>
		<#else>
			<option value="${key}">${datas[key]}</option>
		</#if>
	</#list>
	<#else>
		<#list datas as data>
			<#if key!="">
				<#if value==data[key]?string>
					<option value="${data[key]}" selected="selected">${data[text]}</option>
				<#else>
					<option value="${data[key]}">${data[text]}</option>
				</#if>
			<#else>
				<#if value==data>
					<option value="${data}" selected="selected">${data}</option>
				<#else>
					<option value="${data}">${data}</option>
				</#if>
			</#if>
		</#list>
	</#if>
	</select>
</#macro>

  

 

实现通用分页

13.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#import "/inc/pager.ftl" as my />
<@my.pager url="#" totalPage=150 curPage=145 class="pagers" showPageNum=20 />
</body>
</html>

pager.ftl

<#macro pager url totalPage curPage=1 class="" showPageNum=15>
	<#local halfPage=(showPageNum/2)?int/>
	<#if (halfPage>=curPage)>
		<@showPage start=1 end=curPage url=url class=class curPage=curPage/>
		<@showPage start=curPage+1 end=showPageNum curPage=curPage url=url class=class/>
	<#else>
		<@showPage start=curPage-halfPage end=curPage url=url class=class curPage=curPage/>
		<#if (curPage+halfPage>totalPage)>
			<#local endPage=totalPage/>
		<#else>
			<#local endPage=curPage+halfPage/>
		</#if>
		<@showPage start=curPage+1 end=endPage url=url class=class curPage=curPage/>
	</#if>
</#macro>

<#macro showPage start end curPage url class>
	<#list start..end as page>
		<#if curPage==page>
			[${page}]
		<#else>
			<a href="${url}" class="${class}">${page}</a>
		</#if>
	</#list>
</#macro>

 

  

实现通用的文章显示

14.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<#macro showArt cid titleNum>
	<#nested>
	<ul>
	<#local articles=arts[cid]/>
	<#list articles as art>
		<li><span><a href="">
		<#if (art.title?length>titleNum)>
			${art.title[0..titleNum]}...
		<#else>
			${art.title}
		</#if>
		</a></span>
		</li>
	</#list>
	</ul>
</#macro>

<@showArt cid="1" titleNum=7>
	<h1>全明星替补名单公布</h1>
</@showArt>


<@showArt cid="2" titleNum=10>
	<h1>曝湖人不考虑交易魔兽</h1>
</@showArt>
</body>
</html>

 
FreeMarker Basic_第2张图片
 

6.JUnit Tests

FreeMarker Basic_第3张图片
 
 

 

 

 

你可能感兴趣的:(FreeMarker Basic)