欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Freemarker深入解析

程序员文章站 2022-04-29 20:59:12
...

一:创建一个Configuration实例

// Where the application is initialized; in general you do this ONLY ONCE in the application life-cycle!
    Configuration cfg = new Configuration();
    cfg.setSomeSetting(...);
    cfg.setOtherSetting(...);
    ...
    
    // Later, whenever the application needs a template (so you may do this a lot, and from multiple threads):
    Template myTemplate = cfg.getTemplate("myTemplate.html");
    myTemplate.process(dataModel, out);

上面是摘自freemarker.template.Configuration类的注释,介绍了这个类的使用方法。(本文的freemarker版本为2.3.20)

这个类是进入freemarker API的主要入口类

从注释可以知道这个类主要的功能:封装了freemarker的配置设置,并可用于模板加载,提供缓存(模板)的能力。

下面从代码里来一一看看是如何实现这些功能的。

public Configuration() {
        cache = new TemplateCache();
        cache.setConfiguration(this);
        cache.setDelay(5000);
        loadBuiltInSharedVariables();
    }

可以看到,默认构造器中涉及一个缓存行为,原来上面说的缓存能力是这个TemplateCache类里面写的。先不用管TemplateCache类的细节。先将这个构造流程看一遍。

cache.setConfiguration(this);

这一句将当前这个Configuration类通过setConfiguration方法注入到TemplateCache这个类中。

loadBuiltInSharedVariables方法加载了freemarker内建的配置,包括xml、html格式的文件的特殊字符转义工具类,还有空格等的处理。

构造了Configuration的实例后,要做一些自定义配置,比如设置编码

configuration.setDefaultEncoding("utf-8");

二:创建数据模型

这里是按照官方文档顺序,非入门可跳过直接看三:获取模板。

可以使用java.lang和java.util包中的类,还可以自定义Java Bean类型来构建数据对象。

 

三:获取模板

设置模板加载路径

configuration.setClassForTemplateLoading(this.getClass(), "/template");

上面的方法是告诉freemarker模板加载路径,具体看代码:

public void setClassForTemplateLoading(Class clazz, String pathPrefix) {
        setTemplateLoader(new ClassTemplateLoader(clazz, pathPrefix));
    }

ClassTemplateLoader用于保存传入的参数,构造一个可以确定模板路径的对象,freemarker可以调用其父类URLTemplateLoader的findTemplateSource方法获取模板在运行时的路径。

Freemarker将模板加载的工作抽象为TemplateLoader接口:

Freemarker深入解析

ClassTemplateLoader是TemplateLoader接口的一种实现,查找模板路径的方法一般定义在findTemplateSource方法中,然而ClassTemplateLoader本身没有复写findTemplateSource方法,而是使用父类URLTemplateLoader的findTemplateSource方法,URLTemplateLoader的findTemplateSource方法又需要使用到ClassTemplateLoader的getURL方法,所以ClassTemplateLoader的模板加载是在getURL方法中完成的

URLTemplateLoader的findTemplateSource方法:

public Object findTemplateSource(String name)
    throws
    	IOException
    {
        URL url = getURL(name);
        return url == null ? null : new URLTemplateSource(url);
    }

使用构造ClassTemplateLoader传入的path和后面将要设置的模板名称name拼接出模板全路径,然后使用类加载器的方式去查找资源,返回运行时的统一资源定位符URL。

protected URL getURL(String name)
    {
        String fullPath = path + name;
        
        // Block java.net.URLClassLoader exploits:
        if (path.equals("/") && !isSchemeless(fullPath)) {
            return null;
        }
        
        return loaderClass.getResource(fullPath);
    }

通过查看setTemplateLoader方法的注释文档可以知道,官方支持三种方式设置模板加载路径:

1. 通过 Class.getResource():setClassForTemplateLoading(Class, String);

2. 通过设置具体目录:setDirectoryForTemplateLoading(File)

3. 如果是web项目,也可以通过ServletContext加载:setServletContextForTemplateLoading(Object, String)

 

TemplateLoader接口层次:

Freemarker深入解析

由上图可知,TemplateLoader还有多种实现,即其他的获取模板路径的方式。后面会再写一篇Spring集成freemarker,是如何加载freemarker模板的。

接着看:

public synchronized void setTemplateLoader(TemplateLoader loader) {
        createTemplateCache(loader, cache.getCacheStorage());
    }

setTemplateLoader中调用createTemplateCache方法,可以想象,这里涉及缓存模板的逻辑了。

cache.getCacheStorage(),返回一个CacheStorage实例,CacheStorage是真正缓存模板的,它有几种实现:

Freemarker深入解析

 

参考:http://freemarker.foofun.cn/pgui_quickstart_createdatamodel.html

相关标签: freemarker