浅谈 FreeMarker 模板引擎

原文地址 https://www.heayan.com/articles/2018/02/28/1519825125353.html

前言

FreeMarker 是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本 (HTML 网页,电子邮件,配置文件,源代码等) 的通用工具。 它不是面向最终用户的,而是一个 Java 类库,是一款程序员可以嵌入他们所开发产品的组件。模板编写为 FreeMarker Template Language (FTL)。它是简单的,专用的语言, 不是 像 PHP 那样成熟的编程语言。 那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。

模板引擎分为前台模板引擎、后台模板引擎,FreeMarker 是一款后台模板引擎。由于浏览器 JavaScript 脚本可以人为禁用,建议在使用模板引擎时,优先考虑后台模板引擎。本文以 FreeMarker2.3.26 版本作为分析对象。

工作原理

FreeMarker 通过数据模型、模板,进行组装获得输出对象。输出对象可以是 HTML 页面、电子邮件、配置文件、源代码等。FreeMarker 的模板编写,需要使用 FTL 标签库 FTL 标签库。FTL 标签库类似于 JSTL 标签库,后台通过 JSTL 标签库,将 JSP 文件中的变量动态替换为数据;FreeMarker 通过 FTL 标签库,将模板中的变量动态替换为数据。如图所示:

overview.png

示例代码

FreeMarker 模板示例。通过创建一个 HTML 文件,后缀改为.ftl 格式,将需要动态解析的数据用表达式代替。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>FreeMarker Template Demo</title>
</head>
<body>
    欢迎来到 ${name}宠物商店,我们的联系地址是 ${address},目前我们有以下宠物待售:
    <table>
        <tr>
            <td>昵称</td>
            <td>品种</td>
        </tr>
        <#list dogs as dog>
        <tr>
            <td>${dog.name}</td>
            <td>${dog.varieties}</td>
        </tr>
        </#list>
    </table>
</body>
</html>

FreeMarke 支持哈希表、序列、集合等数据类型, 这些数据类型的数据都可以作为数据模型直接使用,而无需额外创建对象封装。最后,将数据模型与模板整合、输出或保存。

package demo.freemarker.servlet;

import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import demo.freemarker.entity.Dog;
import demo.freemarker.entity.Store;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

public class FreeMarkerServlet extends HttpServlet{

    /**
     * 
     */
    private static final long serialVersionUID = -7620561776035469936L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        /* 数据模型 data-model */
        Dog d1 = new Dog("d1", "小花狗", "德国牧羊犬");
        Dog d2 = new Dog("d2", "大黄狗", "哈士奇");
        Dog d3 = new Dog("d3", "小咖啡", "泰迪");
        List<Dog> dogs = new ArrayList<Dog>();
        dogs.add(d1);
        dogs.add(d2);
        dogs.add(d3);
        Store store = new Store("st1", "宠物专卖北京店", "北京市海淀区",dogs);

        try {
            /* 配置信息 */
            Configuration cfg = new Configuration(Configuration.VERSION_2_3_26);
            cfg.setDirectoryForTemplateLoading(new File(req.getSession().getServletContext()
                    .getRealPath("/freemarker")));// 文件目录路径
            cfg.setDefaultEncoding("UTF-8");
            cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

            /* 模板 */
            Template temp = cfg.getTemplate("storetemp.ftl");
            /* 数据模型与模板组合 */
            Writer out = new OutputStreamWriter(System.out);
            temp.process(store, out);
            out.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TemplateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        super.doPost(req, resp);
    }
}

应用场景

截至目前,、腾讯新闻、网易新闻、阿里巴巴采购批发等等网站,均对模板引擎有所应用。具体使用的是前台模板引擎,还是后天模板引擎, 尚且无法知晓。有小伙伴可能会问为什么要使用模板引擎?使用模板引擎将页面静态化,一可以在页面在页面访问过程中,无需再次访问数据库,降低响应延迟。二有助于搜索引擎收录,有利于 SEO 优化。

版权声明:版权所有,转载请注明原文地址。