使用方法:${rand(1000)} 。
FreeMarker 自定义模版文件加载器
模版文件加载器用来告诉 FreeMarker 引擎到什么地方去加载模版文件。 FreeMarker 自带了三种文件加载器,分别是:文件目录加载器、类路径加载器以及 Web 上下文加载器。当在 Web 环境中使用 FreemarkerServlet 来加载模版文件时,默认使用第三种加载器,并通过 Servlet 的配置 TemplatePath 来指定模版文件所存放的路径,该路径是相对于 Web 的根目录的。
在某种情况下,我们可能会希望把模版文件的源码进行加密处理,例如我们使用 DES 加密方式将模版源文件加密后进行存储,然后我们通过自行实现一个加密的模版文件加载器来读取这些模版文件,解密后交给 FreeMarker 引擎解释执行并得到执行的结果。 FreeMarker 为模版文件加载器定义了一个统一的接口 —— TemplateLoader ,该接口有以下四个方法:
| closeTemplateSource | 关闭模版资源 |
| findTemplateSource | 根据名称返回指定的模版资源 |
| getLastModified | 返回模版资源最后一次修改的时间 |
| getReader | 返回读取模版资源的 Reader |
为了简单起见,我们可以在 FreeMarker 自带的加载器上进行扩展,重写 getReader 方法对读取到的模版文件内容进行解密后生成一个新的 Reader 实例并返回(详细过程不再叙述)。
FreeMarker 自带的几个 TemplateLoader 分别是:
- ClassTemplateLoader :基于类路径的模版加载器
- FileTemplateLoader :基于文件目录的模版加载器
- MultiTemplateLoader :多种加载器的混合
- StringTemplateLoader :基于字符串的模版加载器
- URLTemplateLoader :基于 URL 的模版加载器
- WebappTemplateLoader :基于 Web 上下文的模版加载器
重载模版加载器后通过下面代码使之生效:
cfg.setTemplateLoader(loader) |
FreeMarker 缓存处理
FreeMarker 的缓存处理主要用于模版文件的缓存,一般来讲,模版文件改动不会很频繁,在一个流量非常大的网站中,如果频繁的读取模版文件对系统的负担还是很重的,因此 FreeMarker 通过将模版文件的内容进行缓存,来降低模版文件读取的频次,降低系统的负载。
当处理某个模版时,FreeMarker 直接从缓存中返回对应的 Template 对象,并有一个默认的机制来保证该模版对象是跟模版文件同步的。如果使用的时候 FreemarkerServlet 时,有一个配置项 template_update_delay 用来指定更新模版文件的间隔时间,相当于多长时间检测一下是否有必要重新加载模版文件,0 表示每次都重新加载,否则为多少毫秒钟检测一下模版是否更改。
FreeMarker 定义了一个统一的缓存处理接口 CacheStorage ,默认的实现是 MruCacheStorage 最近最少使用的缓存策略。一般情况下,很少需要对缓存进行扩展处理。您可以通过下面的代码指定最大缓存的模版数:
cfg.setCacheStorage(new freemarker.cache.MruCacheStorage(20, 250)) |
其中第一个参数是最大的强引用对象数,第二个为最大的弱引用对象数。这两个值 FreeMarker 默认的是 0 和 Integer.MAX_VALUE,表明模版缓存数是无限的。
FreeMarker 异常处理
当使用 FreeMarker 做为模版引擎的时候,可能发生的异常包括:
配置异常:配置异常指的是 FreeMarker 初始化时发生的异常,例如错误的配置导致,该异常时由 FreeMarker 的 API 抛出来的。
模版加载异常:模版加载异常可能是模版不存在或者没有读权限,或者是解析模版时发生错误,例如模版语法错误等。
模版执行异常:模版执行异常是指模版已经成功的加载但在执行过程中由于代码执行错误所抛出的异常,这类异常一般都是用户的代码导致。
正常情况下,前两种异常会在开发过程中就会发现并得以解决,而第三种异常往往跟实际的运行环境和数据有关,例如由于某些数据不存在导致的空指针异常等等。因此第三种异常才是我们真正需要关心以及监控的。
为此,FreeMarker 定义了一个统一的异常处理接口 TemplateExceptionHandler 。该接口只有一个方法如下:
void handleTemplateException(TemplateException te,
Environment env,
java.io.Writer out)
|
通过调用 cfg.setTemplateExceptionHandler 来使用自定义的异常处理方法。下面是一个简单的异常处理扩展的例子:
清单 8. 异常处理扩展的例子
class MyTemplateExceptionHandler implements TemplateExceptionHandler {
public void handleTemplateException(TemplateException te,
Environment env, java.io.Writer out)
throws TemplateException {
try {
out.write("[ERROR: " + te.getMessage() + "]");
} catch (IOException e) {
throw new TemplateException(
"Failed to print error message. Cause: " + e, env);
}
}
}
...
cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());
|
Eclipse 的 FreeMarker 插件
为了方便编写 FreeMarker 模版,您可以使用 FreeMarker IDE 这个 Eclipse 插件。该插件具有语法高亮、错误提示等功能。虽然该插件还有很多问题,而且已经很久没更新了,但也能很好地使用。
总结
从上面对于 FreeMarker 的可扩展性的介绍来看,FreeMarker 确实是一个功能非常之强大的模版引擎,可以说远在 Velocity 之上。不过从使用的直观程度以及上手的时间来看,其复杂度也大大的超过了 Velocity 。当我们在面临这两个模版引擎的选择时,不能只是从功能或者容易上手的角度来决定,更应该根据业务本身的需要综合进行比较。(责任编辑:A6)
3G Eden
RSS