当前位置: 移动技术网 > IT编程>开发语言>Java > FreeMarker配置(Configuration)

FreeMarker配置(Configuration)

2019年07月22日  | 移动技术网IT编程  | 我要评论

美睛优品,神鬼传奇龙鳞坐标,言言盛夏

p> 基础

configuration 是一个存放应用级别(application level)公共配置信息,以及模版(template)可使用的全局共享变量的一个对象。同时它还负责模版(template)实例的创建以及缓存。configuration 实际上是freemarker.template.configuration 对象的实例,使用其构造函数创建。通常应用使用一个共享的单实例configuration 对象。

configuration 对象可被template 对象的方法使用,每一个模版实例都关联与一个configuration 实例,它是通过template 的构造函数被关联进去的,通常是你使用这个方法来configuration.gettemplate 获得模版对象的。

 

共享变量

共享变量是那些定义给所有模版(template)使用的变量。你可以通过configuration对象的setsharedvariable 方法来添加共享变量。

configuration cfg = new configuration(); ... cfg.setsharedvariable("wrap", new wrapdirective()); cfg.setsharedvariable("company", "foo inc."); // using objectwrapper.default_wrapper

所有与该configuration 对象关联的模版实例都就可以通过获得to_upper 转换器,company 来获得字符串,因此你不需要再一次次的往root 中添加这些变量了。如果你往root 添加同名的变量,那么你新添加的变量将会覆盖之前的共享变量。

警告!

如果configuration 对象被多线程调用,那么不要使用templatemodel 实现类作为共享变量,因为他们是非线程安全的,例如基于servlet 的web 站点就是这种情况。

configuration 对象初始化时已经包含一些共享转换器变量:

名字类

name class capture_output freemarker.template.utility.captureoutput compress freemarker.template.utility.standardcompress html_escape freemarker.template.utility.htmlescape normalize_newlines freemarker.template.utility.normalizenewlines xml_escape freemarker.template.utility.xmlescape

 

 

配置参数

配置参数是那些可以影响freemarker 运行行为的那些命名参数。例如locale,number_format。

配置参数存储在configuration实例中,它可以被模版实例(template)修改。例如,你在configuration中设置了locale等于"en_us",那么所有的模版对象都会使用,"en_us"除非你在单个模版实例中利用setlocale方法修改了默认配置。因此configuration设置的参数可以当作是默认参数,它可以被template一级设置的参数覆盖,而它们两者设置的参数信息又可以被环境中设置的参数所覆盖(也就是模版文件指令设置的)如下:

${1.2}<#setting locale="en_us">${1.2}


这种调用方式你可以想象成3 个层(配置对象层,模版层,运行环境层)下面表格中显示了每一层对于参数的设置:

setting a setting b setting c setting d setting e setting f layer 3:environment 1 - - 1 - - layer 2:template 2 2 - - 2 - layer 1:configuration 3 3 3 3 - -

那么配置参数的最终结果分别是:a = 1, b = 2, c = 3, d = 1, e = 2.而f 参数很可能就是null。

如果要查询可设置的参数列表,你可以查阅freemarker api 文档的以下两个部分:
所有层的配置

freemarker.core.configurable.setsetting(string, string)


coniguration 层的配置

freemarker.template.configuration.setsetting(string,string)


加载模板


模版加载器

模版加载器是基于抽象路径("index.ftl"或"products/catalog.ftl")加载原始数据的那些对象,而究竟加载何种资源(目录中的文件数据还是数据库中的数据)取决于具体的加载器实现。当你调用cfg.gettemplate 时,freemarker 将会询问你之前配置给configuration 对象的模版加载器,有该模版加载器负责文件的载入。

内建的模版加载器
你可以用以下三个方法来设置模版加载的三种方式

void setdirectoryfortemplateloading(file dir);


或者

void setclassfortemplateloading(class cl, string prefix);


或者

void setservletcontextfortemplateloading(object servletcontext, string path);


以上第一种方式显示的指定了一个文件系统中的目录,freemarker 将会在此目录记载模版,不用说,此目录必须存在,否在会抛出异常。

第二种方式以一个class作为一个输入参数,当你想使用classloader的方式来加载模版的时候,你就可以使用这种方式,这种方式将会调用来寻找模版文件,同时这种模版加载的方式要比前一种稳定一些尤其是在生产系统中。你可以很容易的把资源文件,以及图标等打包到.jar 文件中。

第三种方式把web 应用的上下文以及基路径(相对与wen-inf 的父路进来说)作为参数。该种方式的模版加载器将会从web 应用上下文种加载模版。

从多个位置加载模版

如果你想从多个位置加载模版的话,你可以分别创建与不同位置对应的单个模版加载器,然后把它们包裹到一个名叫multitemplateloader模版加载器中,最终通过方法settemplateloader(templateloader loader)把其设置给configuration 对象,以下有一个从两个不同位置加载模版的例子:

import freemarker.cache.*; // template loaders live in this package ... 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 将会首先在路径/tmp/templates中搜索模版文件,如果没有找到那么回到路径/usr/data/templates中搜索,如果还没有找到,那么则会尝试用class-loader的方式加载。

从其他资源中获取模版文件

如果在这些内建的模版加载器中没有一个符合你的要求,那么你可以自己定制一个模版加载器,只需要实现freemarker.cache.templateloader 接口就可以了,然后通过方法settemplateloader(templateloader loader)把其传递给configuration对象。

缓存模版

freemarker缓存模版的意思就是,当你通过gettemplate方法获取一个模版的时候,freemarker不仅会返回一个template对象,而且会缓存该对象,当你下一次以相同的路径请求模版的时候,它就会返回缓存中的模版对象。如果你改变了模版文件,那么当你下一次获取模版的时候,freemarker会自动重新加载,重新解析模版。虽然如此,但是如果直接判断一个文件是否修改过是一个耗时的操作,那么freemarker 在configuration 对象级别提供了一个配置参数“update delay”。该参数的意思是freemarker多长时间去判断一次模版的版本,默认设置是5秒钟,也就是每个5秒就会判断模版是否经过修改,如果你想实时的判断,那么设置该参数为0。另外一点需要注意,并不是所有的加载器都支持这种判断方式,举例来说基于class-loader 的模版加载器就不会发现你修改过模版文件。

对于删除缓存中的模版freemarker 是这么做的,你可以使用configuration 对象方法cleartemplatecache 以手工的方式清楚缓存中的模版对象。而实际上缓存部分可以作为一个组建加入到freemarker 中(也就是它可以使用第三方缓存方案)你可以通过设置cache_storage 这个参数来实现。对大多数开发者来freemarker 自带的freemarker.cache.mrucachestorage 实现已经足够了。这个缓存使用2 个级别的most recently used(最近最多用)策略。在第一个级别,所有的缓存条目都是使用强引用(strongly referenced:条目并不会被jvm 所清楚,与其相对的弱引用softly reference)直到达到最大时间,那些最近最少使用的条目就会被迁移到二级缓存。在这个级别条目都是使用弱引用直到达到过期。若引用与强引用的区域的大小是可以在构造函数中设置的,例如你想把强引用区域设置为20,弱引用区域设置为250,那你可以使用以下代码:

cfg.setcachestorage(new freemarker.cache.mrucachestorage(20, 250))


由于mrucachestorage 是默认的缓存实现,那么你也可以这样设置:

cfg.setsetting(configuration.cache_storage_key,"strong:20, soft:250");


当你创建一个新的configuration时,其默认使用mrucachestorage缓存实现且默认的值maxstrongsize等于0,maxsoftsize等于integer.max_value(也就是理论最大值)。但是对于高负荷的系统来说,我们建议maxstrongsize 设置成一个非0 的数值,不然会导致频繁的重新加载,重新解析模版。

 

异常处理

可能产生的异常

freemarker 产生的异常一般可归以下几类:

freemarker 初始化阶段产生的异常: 通常在你的应用中仅需要初始化freemarker 一次,而当在这个时间段类产生的异常就叫做初始化异常。

加载解析模版期的异常:当你通过configuration.gettemplate()方法获取模版的时候(如果模版之前没有被缓存),将会产生两类异常:

ioexception:由于模版没有找到,或在读取模版的时候发生其他的io异常,比如你没有读取该文件的权限等等; freemarker.core.parseexception 由于模版文件的语法使用不正确;

执行期间的异常:当你调用template.process(...)方法的时候,会抛出两类异常:

ioexception 往输出写数据时候发生的错误; freemarker.template.templatexception其他运行期产生的异常,比如一个最常见的错误就是模版引用了一个不存在的变量;

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网