首先我们定义一个这样的块指令:#cache( “ CacheRegion ” , ” Key ” ) ,其中第一个参数为缓存区域、第二个参数为对应缓存数据的键值。该指令自动将包含在指令内部的脚本执行后的结构缓存起来,当第一次请求时检查缓存中是否存在此 HTML 片段数据,如果存在就直接输出到页面,否则执行块指令中的脚本,执行后的结果输出到页面同时保存到缓存中以便下次使用。使用方法如下所示:
#cache("News","home")
## 读取数据库中最新新闻并显示
<ul>
#foreach($news in $NewsTool.ListTopNews(10))
<li>
<span class='date'>
$date.format("yyyy-MM-dd",${news.pub_time})
</span>
<span class='title'>${news.title}</span>
</li>
#end
</ul>
#end |
其中 $NewsTool.ListTopNews(10) 是用来从数据库中读取最新发布的 10 条新闻信息。
接下来我们来看 #cache 这个指令对应的源码:
/**
* Velocity模板上用于控制缓存的指令
* @author Winter Lau
* @date 2009-3-16 下午04:40:19
*/
public class CacheDirective extends Directive {
final static Hashtable<String,String> body_tpls = new Hashtable<String, String>();
@Override
public String getName() { return "cache"; } //指定指令的名称
@Override
public int getType() { return BLOCK; } //指定指令类型为块指令
/* (non-Javadoc)
* @see org.apache.velocity.runtime.directive.Directive#render()
*/
@Override
public boolean render(InternalContextAdapter context, Writer writer, Node node)
throws IOException, ResourceNotFoundException, ParseErrorException,
MethodInvocationException
{
//获得缓存信息
SimpleNode sn_region = (SimpleNode) node.jjtGetChild(0);
String region = (String)sn_region.value(context);
SimpleNode sn_key = (SimpleNode) node.jjtGetChild(1);
Serializable key = (Serializable)sn_key.value(context);
Node body = node.jjtGetChild(2);
//检查内容是否有变化
String tpl_key = key+"@"+region;
String body_tpl = body.literal();
String old_body_tpl = body_tpls.get(tpl_key);
String cache_html = CacheHelper.get(String.class, region, key);
if(cache_html == null || !StringUtils.equals(body_tpl, old_body_tpl)){
StringWriter sw = new StringWriter();
body.render(context, sw);
cache_html = sw.toString();
CacheHelper.set(region, key, cache_html);
body_tpls.put(tpl_key, body_tpl);
}
writer.write(cache_html);
return true;
}
} |