在用FreeMarker的时候通常都需要自己写一个ftl模板。
但它又是怎么加载的呢。
在FreeMarker中默认提供了两种模板加载方式
都实现了TemplateLoader接口
关键的方式
//寻找模板
public Object findTemplateSource(String name);
//返回模板内容
public Reader getReader(Object templateSource, String encoding);
不能的加载器实现的findTemplateSource不同,基本上都是从不同的方式进行加载模板,如不同的路径。
1、FileTemplateLoader
从templateLoaderPaths目录下找模板
如配置
<property name="templateLoaderPaths" value="/WEB-INF"/>
就能在当前项目内的目录WEB-INF下面找模板文件
2、abstract URLTemplateLoader
该类提供一个方式protected abstract URL getURL(String name);
还有一个已经实现好的getReader(URL url,String encoding)方法;
所以想法就是通过不同的方式找到模板的URL即可。
其子类ClassTemplateLoader实现为在
protected URL getURL(String name)
{
return loaderClass.getResource(path + name);
}
如此
我们可以为自己的需要添加新的模板加载器
实现TemplateLoader接口也好,继承URLTemplateLoader也好,都可以让FreeMarker用自己的加载器来加载模板。
上述两种方法中第一种只能加载项目内的ftl文件。第二种还不知道加载什么文件。
感觉还是不是很方便,如果要加载项目外部的模板文件的时候该怎么办呢。
那么,我的做法就是继承URLTemplateLoader,实现getUrl()方法。
package com.freemarker.template.loader;
import java.io.IOException;
import java.net.URL;
import freemarker.cache.URLTemplateLoader;
public class MutiUrlTemplateLoader extends URLTemplateLoader {//文件协议(我只用到本地文件,所以默认file协议)
private String protocol = "file:/";
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public void setPath(String path) {
this.path = path;
}
private String path = "";
@Override
protected URL getURL(String name) {
URL url = null;
try {
url = new URL(this.protocol + this.path + name);//测试URL是否有效
url.openConnection().connect();
} catch (IOException e) {
return null;
}
return url;
}
}
就这样,自己的加载器就好了,其它的东西都原模原样,什么都不需要,因为父类已经有getReader方法了。
另外一种文件实现Templateloader接口没有去写过,但应该都是一样的。
上面说了这么多,那怎么把加载器配置到FreeMarker中呢。
FreeMarker支持多个模板加载器。
按顺序加载文件,如果找到模板则不加载了。
FreeMarker提供了一个preTemplateLoaders,就是先用哪个加载器来加载模板了。
配置:
<property name="preTemplateLoaders">
<list>
<bean class="com.freemarker.template.loader.MutiUrlTemplateLoader"/>
</list>
</property>
在FreeMarkerConfigurationFactory中有如下代码能说明它做的:
// Register template loaders that are supposed to kick in early.
if (this.preTemplateLoaders != null) {
this.templateLoaders.addAll(this.preTemplateLoaders);
}
// Register default template loaders.
if (this.templateLoaderPaths != null) {
for (String path : this.templateLoaderPaths) {
this.templateLoaders.add(getTemplateLoaderForPath(path));
}
}
它先把预加载的加载器先添加到加载器列表中。
在它加载的时候会遍历加载器去加载模板,先加载到的就结束加载。
整个过程都弄好了。现在FreeMarker就能加载到项目外部的模板文件了。但是被FreeMarker加载的文件不能被删除,它能被修改。