本文主要是介绍FreeMaker入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
第一章 简介
1 什么是FreeMaker
FreeMaker是一款模板引擎,即基于模板,用来生成文本的工具。可以用来实现MVC模式。FreeMaker基于BSD协议。是ISO认证的开源软件。
2. 简介
如果你的在线商店需要这样的页面如:
<html>
<head> <title>Welcome!</title>
</head>
<body> <h1>Welcome tntxia!</h1> <p>Our latest product: <a href="products/greenmouse.html">green mouse</a>!
</body>
</html>
这里tntxia是用户名。应该使用动态。
FreeMaker是这样实现的。
<html>
<head> <title>Welcome!</title>
</head>
<body> <h1>Welcome ${user}!</h1> <p>Our latest product: <a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>
FreeMaker可以使用Map、List对象,也可以自定义的数据模型。
${…}:FreeMaker会使用动态的数据改成$里面的内容。
FTL tags 标签(FreeMarker 模板的语言标签) :与HTML标签相似,一般以#开关,但也可以自定义。
Comments 注释:<#-- -->
可以增加一个Servlet:
package com.tntxia.freemaker.test;import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;public class HelloFreeMarker extends HttpServlet {/*** */private static final long serialVersionUID = 6255189103129788283L;public HelloFreeMarker() {super();}// 负责管理FreeMarker模板的Configuration实例private Configuration cfg = null;public void init() throws ServletException {// 创建一个FreeMarker实例cfg = new Configuration();// 指定FreeMarker模板文件的位置cfg.setServletContextForTemplateLoading(getServletContext(),"/WEB-INF/templates");}public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doPost(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 建立数据模型Map root = new HashMap();root.put("message", "hello world");root.put("name", "聂靖宇");root.put("num", 5);DataModel data = new DataModel();root.put("data", data);// root.put("personList", list);// 获取模板文件Template t = cfg.getTemplate("test1.ftl");// 开始准备生成输出// - 使用模板文件的Charset作为本页面的charset// - 使用text/html MIME-typeresponse.setContentType("text/html; charset=" + t.getEncoding());Writer out = response.getWriter();// 合并数据模型和模板,并将结果输出到out中try {t.process(root, out); // 往模板里写数据} catch (TemplateException e) {e.printStackTrace();}}public void destroy() {super.destroy();}
}
在WEB-INF里面增加一个template的文件,增加一个FTL文件:
test1.ftl
<html><head> <title>Hello Word</title> </head> <body>
<#-- 测试注释 -->
<h3>${message},${name} ${data.test}</h3> <#if num > 5 >num is 5</#if></body> </html>
1.1 指令
1.1.1 if指令
<#if user == "Big Joe">, our beloved leader</#if>!
通过if指令,可以让符合条件的内容显示。
当condition 的判断结果为 false(布尔值)时,在<#if condition>和</#if>标签之间的内容将会被略过。
使用<#else>标签可以指定当条件为假时程序执行的内容。例如:
<#if animals.python.price < animals.elephant.price> Pythons are cheaper than elephants today. <#else> Pythons are not cheaper than elephants today. </#if>
1.1.2 list指令
用List指令可以实现循环输出
如:
<p>We have these animals:
<table border=1><tr><th>Name<th>Price<#list animals as being><tr><td>${being.name}<td>${being.price} Euros</#list>
</table>
list 指令的一般格式为:
<#list sequence as loopVariable>repeatThis</#list>
repeatThis 部分将会在给定的sequence 遍历时在每项中重复,从第一项开始,
一个接着一个。在所有的重复中,loopVariable 将持有当前项的值。这个循环变量仅
存在于<#list …>和</#list>标签之间。
1.1.3 include指令
引入一个模板:
<#include "test.ftl">
<#include "/test.ftl">
文件的位置与模板文件夹一致。
1.1.4 不存在的变量的处理
${user!"Asynonymous"}<#if user??>welcome ${user}<#else>Asynonymous Again</#if>
FreeMaker容器:
2.2.3 容器
这些值存在的目的是为了包含其他变量,它们仅仅作为容器。被包含的变量通常是子变
量。容器的类型有:
哈希表:每个子变量都可以通过一个唯一的名称来查找,这个名称是不受限制的字
符串。哈希表并不确定其中子变量的顺序,也就是说没有第一个变量,第二个变量
这样的说法,变量仅仅是通过名称来访问的。 (就像 Java 语言中的 HashMap 一样,
是实现了 Hash 算法的 Map,不记录内部元素的顺序,仅仅通过名称来访问。译者
注)
序列:每个子变量通过一个整数来标识。 第一个子变量的标识符是 0,第二个是 1,
第三个是 2,这样来类推,而且子变量是有顺序的。这些数字通常被称为是子变量
的索引。序列通常比较密集,也就是所有的索引,包括最后一个子变量的,它们和
子变量都是相关联的,但不是绝对必要的。 子变量的数值类型也并不需要完全一致。
集: 从模板设计者角度来看,集是有限制的序列。不能获取集的大小,也不能通过
索引取出集中的子变量,但是它们仍然可以通过 list 指令来遍历。
2.2.4 函数
The average of 3 and 5 is: ${avg(3, 5)}
The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
The average of the price of a python and an elephant is:
${avg(animals.python.price, animals.elephant.price)}
输出结果:
The average of 3 and 5 is: 4
The average of 6 and 10 and 20 is: 12
The average of the price of a python and an elephant is:
4999.5
2.2.5 自定义方法
方法变量在存于实现了 TemplateMethodModel 接口的模板中。这个接口仅包含方法调用表达式调用方法时, exec方法将会被调用。 形参将会包含FTL方法调用形参的值。exec 方法的返回值给出了 FTL 方法调用表达式的返回值。
2.2.6 自定义指令
Java程序员可以使用TemplateDirectiveModel 接口在Java代码中实现自定义指令。详情可以参看 API 文档。
2.2.6.1 第一个示例
模板:
foo
<@upper> bar <#-- 这里允许使用所有的 FTL --> <#list ["red", "green", "blue"] as color> ${color} </#list> baaz
</@upper>
wombat
将会输出:
foo
BAR
RED
GREEN
BLUE
BAAZ
wombat
下面是指令类的源代码:
root.put("upper", new com.example.UpperDirective());
package com.example;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
/** * FreeMarker的用户自定义指令在逐步改变
* 它嵌套内容的输出转换为大写形式
* <p><b>指令内容</b></p>
* <p>指令参数:无 * <p>循环变量:无
* <p>指令嵌套内容:是
*/
public class UpperDirective implements TemplateDirectiveModel
{ public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { // 检查参数是否传入 if (!params.isEmpty()) { throw new TemplateModelException( "This directive doesn't allow parameters."); } if (loopVars.length != 0) { throw new TemplateModelException("This directive doesn't allow loop variables."); } // 是否有非空的嵌入内容 if (body != null) { // 执行嵌入体部分,和 FTL中的<#nested>一样,除了 // 我们使用我们自己的 writer 来代替当前的 output writer. body.render(new UpperCaseFilterWriter(env.getOut())); } else { throw new RuntimeException("missing body"); }
}
/** * {@link Writer}改变字符流到大写形式,
* 而且把它发送到另外一个{@link Writer}中。
*/
private static class UpperCaseFilterWriter extends Writer {
private final Writer out;
UpperCaseFilterWriter (Writer out) { this.out = out;
} public void write(char[] cbuf, int off, int len) throws IOException { char[] transformedCbuf = new char[len]; for (int i = 0; i < len; i++) { transformedCbuf[i] = Character.
toUpperCase(cbuf[i + off]); } out.write(transformedCbuf); } public void flush() throws IOException { out.flush(); } public void close() throws IOException { out.close(); }
}
}
最后,把它放在数据模型里面,如:
root.put("upper", new com.example.UpperDirective());
第二个示例 :Repeat
这篇关于FreeMaker入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!