velocity提供了一些扩展点,如: 指令扩展、事件处理等。本文主要阐述基于事件处理的扩展,并提供一些事例。
本文讨论的velocity版本如下:
URL: http://svn.apache.org/repos/asf/velocity/engine/trunk
Repository Root: http://svn.apache.org/repos/asf
Repository UUID: 13f79535-47bb-0310-9956-ffa450edef68
Revision: 1221660
Node Kind: directory
Schedule: normal
Last Changed Author: nbubna
Last Changed Rev: 1221053
Last Changed Date: 2011-12-20 08:55:01 +0800 (Tue, 20 Dec 2011)
类图:
velocity中提供了一些事件处理扩展:
IncludeEventHandler
InvalidReferenceEventHandler
MethodExceptionEventHandler
ReferenceInsertionEventHandler
本文先简单介绍各个扩展点,最后重点介绍ReferenceInsertionEventHandler
1.IncludeEventHandler(#include()和#parse()对应事件的接口类):
默认实现主要有两个,IncludeNotFound和IncludeRelativePath
IncludeNotFound在#include(x)和#parse(x)加载x之前操作,返回具体的x给指令加载
若x存在,返回x;
若x不存在则返回配置的eventhandler.include.notfound属性对应的模板文件;
若eventhandler.include.notfound对应的文件也不存在直接记录log;
具体代码如下:
IncludeRelativePath在#include(x)和#parse(x)加载x之前操作,返回具体的x给指令加载
增加了相对模板路径的文件加载,避免文章太长,代码不给出了。
2.InvalidReferenceEventHandler(对无效比较的错误提示):
主要在get,set以及其他方法调用时出现细化错误(ParseErrorException)提示内容,当然这个错误是根据eventhandler.invalidreference.exception的设置是否抛出,默认不抛出。
3.MethodExceptionEventHandler(对会抛出异常的方法调用时作友好性处理):
目前实现有两个类:ExceptionGeneratingEventHandler、PrintExceptions,主要对异常作些友好性处理。
以上三个点更接近系统内部的一些规则处理,可扩展性不大,如果使用到,默认实现基本足够,因此不做细讲,我们重点讨论最后一种。
4.ReferenceInsertionEventHandler(变量结果写入事件处理);
这个比较有用是对渲染结果的处理,比如html,javascript,url,java,sql,xml等,这些是比较实用的功能。velocity默认提供了替换html,javascript,java,sql,xml的过滤扩展。
目前定义了四个实现:
EscapeReference escape抽象类,定义公共的外部属性读入和接口
EscapeHtmlReference 过滤html标签,配置属性eventhandler.escape.html.match,实现类StringEscapeUtils.escapeHtml()
EscapeJavaScriptReference 过滤javascript标签,配置属性eventhandler.escape.javascript.match,实现类StringEscapeUtils.escapeJavaScript()
EscapeSqlReference 过滤sql标签,配置属性eventhandler.escape.sql.match,实现替换'为‘’(单引号替换为双引号)
EscapeXmlReference 过滤xml,配置属性eventhandler.escape.xml.match,具体实现类StringEscapeUtils.escapeXml
如果自己要扩展,除了配置多个Reference外也可以采用一个Reference多个条件处理,如果和macros集合,效果会更好,
比如:定义一个宏:
#macro(URL $url_escape_z)
$url_escape_z
#end
我们可以在页面中如下使用
#URL("a&=<>?b")
若在velocity.properties属性中配置对应的过滤器为EscapeURLReference,那么代码在解析时会把#URL()中的变量改成url格式输出。
需要说明的是:
调用到EscapeURLReference并非是#URL标签,而是$url_escape_z
即便是$!url_escape_z活${url_escape_z}活$!{url_escape_z}都不会处理
#URL指令之所以会处理,是因为和对应变量挂钩
若自己在代码中有$url_escape_z变量,该内容也会被处理,因此需要变量名唯一