模板加载器是加载原生文本数据对象。这由具体的模板加载器对象来确定他们取得请求数据时使用了什么样的数据来源(文件夹中的文件,数据等)。当调用cfg.getTemplate(Configuration cfg)时,FreeMarker询问模板加载器是否已经为cfg建立返回给定模板路径的文本,之后FreeMarker解析文本生成模板。
在Configuration中可以使用下面的方法来建立三种模板加载(每种方法都会在其内部新建一个模板加载器对象,然后创建实例来使用):
void setDirectoryForTemplateLoading(File dir); void setClassForTemplateLoading(Class cl, String prefix); void setServletContextForTemplateLoading(Object servletContext, String path);
第一种方法在磁盘的文件系统上设置了一个明确的目录,它确定了从哪里加载模板;FIle参数是一个存在的目录,否则,将会抛出异常。
第二种方法使用了一个Class类型的参数和一个前缀。让用户指定什么时候通过相同的机制来加载模板,用java的ClassLoader来加载类。传入的Class参数会被用来调用Class.getResource()方法来找到模板。参数prefix是给模板的名称来加前缀的。在实际运行的环境中,类加载机制是首选用来加载模板的方法。
第三种方法需要Web应用的上下文和一个基路径作为参数,这个基路径是Web应用根路径(WEB-INF目录的上级目录)的相对路径。那么加载器将会从Web应用目录开始加载模板。尽管加载方法对没打包的.war文件起作用,因为它使用了ServletContext.getResource()方法来访问模板。
如果需要从多个位置加载模板,那就为每个位置都实例化模板加载器对象,将它们包装到一个MultiTemplateLoader的特殊模板加载器,最终将这个加载器传递给Configuration对象的setTemplateLoader(TemplateLoader loader)方法。
例如:
import freemarker.cache.*; // 模板加载器在这个包下 ... FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates")); FileTemplateLoader ftl2 = new FileTemplateLoader(new File("/usr/data/templates")); ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), ""); TemplateLoader[] loaders = new TemplateLoader[] { ftl1, ftl2, ctl }; MultiTemplateLoader mtl = new MultiTemplateLoader(loaders); cfg.setTemplateLoader(mtl);
FreeMarker将会尝试从/temp/templates目录加载模板,如果在这个目录下没有发现请求的模板,它就会继续尝试从/user/data/templates目录下架子啊,如果还没找到,就使用类加载器来加载模板。
如果内建的加载器都不适合使用,那么就需要编写自己的类加载器了,这个类需要实现freemarker.cacke.TemplateLoader接口,然后将它传递给Configuration对象的setTemplateLoader方法。
如果你的模板需要通过URL访问其他模板,那么就不需要实现TemplateLoader接口了,可以选择子接口freemarker.cache.URLTemplateLoader来替代,只需实现getURL方法即可。
解析模板的路径是由模板解析器来决定的。但是要和其他对路径格式要求很严格的组件一起工作。
通常来说,强烈建议模板加载器使用URL风格的路径。
在URL路径中有其他含义时,那么路径中不要使用/, ./, ../ 和:// 。
FreeMarker是会缓存模板的。当调用getTemplate方法时,FreeMarker不但返回了Template对象的结果,而且还会将它存储在缓存中,当下一次再以相同路径调用getTemplate方法时,那么它只返回缓存的Tempalte实例,而不会再次加载和解析模板文件。
如果更改了模板文件,当下次调用模板时,FreeMarker会自动重新载入和解析模板。
要检查模板文件是否改变内容了是需要时间的,有一个Configuration级别的设置被称作“更新延迟”可以用来设置这个时间,默认是5秒。如果想要看到模板立即更新的效果,那么就要把它设置为0.
此外,还可以使用Configuration对象的clearTemplateCache方法手动清空缓存。
何时将一个被缓存了的模板清除的应用策略是由配置的属性cache_storage来确定的,通过这个属性可以配置任何CacheStorage的实现。对于大多数用来来说,使用freemarker.cache.MruCacheStorage就足够了。这个缓存存储实现了二级最近使用的缓存。在第一级缓存中,组件都被强烈引用到特定的最大数目。当超过最大数量时,最近最少使用的组件将被送至二级缓存中。引用强度的大小可以由构造方法来指定。例如:设置强烈部分为20,轻微部分为250:
cfg.setCacheStorage(new freemarker.cache.MruCacheStorage(20, 250))
或者,使用MruCacheStorage昏村,它是默认缓存存储实现:
cfg.setSetting(Configuration.CACHE_STORAGE_KEY, "strong:20, soft:250");
当创建了一个新的Configuration对象时,它使用一个maxStrongSize值为0的MruCacheStorage缓存来初始化,maxSoftSize的值是Integer.MAX_VALUE(也就是说在实际中,是无限大的)。但是使用非0的maxStrongSize对于高负载的服务器来说也许是一个更好的策略。