`
zl198751
  • 浏览: 272989 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Velocity 自定义标签

阅读更多

编写自定义的 Velocity 指令

Velocity 允许您对指令系统进行扩展,在 Velocity 引擎初始化的时候会加载系统内置指令和用户的自定义指令。系统的内置指令已经在 Velocity 的 Jar 包中的 directive.properties 文件中定义,不建议直接修改该文件。而自定义的指令要求用户在 velocity.properties 文件中定义的,例如:userdirective=net.oschina.toolbox.CacheDirective。如果是多个自定义指令则使用逗号隔开。

所有的自定义指令要求扩展 org.apache.velocity.runtime.directive.Directive 这个类。为了更加形象直观的表现 Velocity 自定义指令的优点,接下来我们将以一个实际的应用场景进行讲解。

在该应用场景中,所有的页面请求直接指向 vm 文件,中间没经过任何的控制器。数据是通过 Velocity 的 toolbox 直接读取并显示在页面上。如果数据是来自数据库的,而且访问量非常大的时候,我们就需要对这些数据进行缓存以便快速响应用户请求和降低系统负载。一种方法是直接在 toolbox 的读取数据的方法中进行数据的缓存;另外一种就是我们接下来要介绍的,通过编写自定义的缓存指令来缓存页面上的某个 HTML 片段。

首先我们定义一个这样的块指令:#cache( “ CacheRegion ” , ” Key ” ) ,其中第一个参数为缓存区域、第二个参数为对应缓存数据的键值。该指令自动将包含在指令内部的脚本执行后的结构缓存起来,当第一次请求时检查缓存中是否存在此 HTML 片段数据,如果存在就直接输出到页面,否则执行块指令中的脚本,执行后的结果输出到页面同时保存到缓存中以便下次使用。使用方法如下所示:

  1. #cache("News","home")    
  2.   ## 读取数据库中最新新闻并显示   
  3.   <ul>    
  4.   #foreach($news in $NewsTool.ListTopNews(10))    
  5.      <li>    
  6.       <span class='date'>    
  7.  $date.format("yyyy-MM-dd",${news.pub_time})    
  8.  </span>    
  9.       <span class='title'>${news.title}</span>    
  10.      </li>    
  11.   #end    
  12.   </ul>    
  13.  #end  

其中 $NewsTool.ListTopNews(10) 是用来从数据库中读取最新发布的 10 条新闻信息。

接下来我们来看 #cache 这个指令对应的源码:

  1. /**  
  2.  * Velocity模板上用于控制缓存的指令  
  3.  * @author Winter Lau  
  4.  * @date 2009-3-16 下午04:40:19  
  5.  */  
  6. public class CacheDirective extends Directive {   
  7.   
  8.     final static Hashtable<String,String> body_tpls = new Hashtable<String, String>();   
  9.        
  10.     @Override  
  11.     public String getName() { return "cache"; } //指定指令的名称   
  12.   
  13.     @Override  
  14.     public int getType() { return BLOCK; } //指定指令类型为块指令   
  15.   
  16.     /* (non-Javadoc)  
  17.     * @see org.apache.velocity.runtime.directive.Directive#render()  
  18.     */  
  19.     @Override  
  20.     public boolean render(InternalContextAdapter context, Writer writer, Node node)   
  21.         throws IOException, ResourceNotFoundException, ParseErrorException,   
  22.         MethodInvocationException    
  23.     {   
  24.         //获得缓存信息   
  25.         SimpleNode sn_region = (SimpleNode) node.jjtGetChild(0);   
  26.         String region = (String)sn_region.value(context);   
  27.         SimpleNode sn_key = (SimpleNode) node.jjtGetChild(1);   
  28.         Serializable key = (Serializable)sn_key.value(context);   
  29.         
  30.         Node body = node.jjtGetChild(2);   
  31.         //检查内容是否有变化   
  32.         String tpl_key = key+"@"+region;   
  33.         String body_tpl = body.literal();   
  34.         String old_body_tpl = body_tpls.get(tpl_key);   
  35.         String cache_html = CacheHelper.get(String.class, region, key);   
  36.         if(cache_html == null || !StringUtils.equals(body_tpl, old_body_tpl)){   
  37.             StringWriter sw = new StringWriter();   
  38.             body.render(context, sw);   
  39.             cache_html = sw.toString();   
  40.             CacheHelper.set(region, key, cache_html);   
  41.             body_tpls.put(tpl_key, body_tpl);   
  42.         }   
  43.         writer.write(cache_html);   
  44.         return true;   
  45.     }   
  46. }  

Directive 是所有指令的基类,Directive 是一个抽象类,它有三个方法必须实现的,分别是:

getName:返回指令的名称
getType:返回指令的类型,行指令:LINE、块指令:BLOCK
render:指令执行的入口
其中 render 方法的最后一个参数 node 表示为该指定对应在 Velocity 模板中的节点对象,通过调用 node 的 jjtGetChild 方法可以获取到传递给该指令的参数以及包含在该指令的脚本内容。

上面的代码中,首先获取传递给指令的参数,也就是缓存的区域名和对应缓存数据的键值。接着判断距上次数据被缓存时,指令所包含的脚本代码是否有更改(以便页面开发人员修改了 vm 脚本时自动刷新缓存数据),然后判断缓存中是否已有数据。当缓存中无数据或者页面代码被修改时,重新执行块指令中的脚本并将执行的结果置入缓存,否则直接将缓存中的数据输出到页面。

上述例子中,传递给 #cache 指令的参数也可以是某个变量,例如

 #set($region = "news")
 #set($key = "home")
 #cache("CACHE_$region",$key)


如此,便以很小的代码侵入,来实现页面的缓存。

分享到:
评论

相关推荐

    Velocity自定义标签无法注入spring的Service解决办法

    用springMVC+velocity时,当使用自定义标签,发现自定义标签无法注入spring的其它服务类,归根源码发现,velocity的源码中有一段,有一段代码永远获取的是新实例。所以,把这个地方的源码改了,所以使用这个的时候,...

    Velocity-crx插件

    Velocity Chrome扩展显示关于您在Asana中查看的数据的预构建报告,并显示您构建的任何自定义速度报告。 例如,如果您正在查看名为“错误”的ASANA项目,则速度Chrome扩展会显示有关错误项目的预构建报告。 您还可以...

    Struts2 标签库

    Struts2允许在页面中使用自定义组件,这完全能满足项目中页面显示复杂,多变的需求。 005 Struts2的标签库有一个巨大的改进之处,struts2标签库的标签不依赖于任何表现层技术,也就是说strtus2提供了大部分标签,...

    veloeclipse

    插件Veloeclipse:Velocity+Html 的编辑工具,除了提供不同颜色显示velocity和html的语法外,还提供根据velocity和html的tag自动对齐,tag和标签的自动提示等,真是开发社团里有什么需求,就有什么开源的东东出来...

    速度「Velocity」-crx插件

    允许自定义图标安排和码头安置,以及移动未来的小部件来!速度也会告诉你当前的天气,不仅在一个标准的图标和数字时尚,但动画的背景匹配! Velocity会要求你先创建一个帐户并签名,但是会让你继续前进,这主要是...

    struts2 学习例子

    Struts2允许在页面中使用自定义组件,这完全能满足项目中页面显示复杂,多变的需求。 Struts2的标签库有一个巨大的改进之处,struts2标签库的标签不依赖于任何表现层技术,也就是说strtus2提供了大部分标签,可以在...

    struts2讲义_吴峻申

    5.7 Struts2自定义标签实现图形验证功能 121 第6章 Struts2非JSP视图技术 125 6.1 velocity视图技术使用介绍 125 6.2 freemarker视图技术使用介绍 128 6.3 JasperReports报表视图技术使用介绍 130 第7章 Struts2类型...

    深入浅出Struts2(附源码)

    作者处处从实战出发,在丰富的示例中直观地探讨了许多实用的技术,如数据类型转换、文件上传和下载、提高Struts 2应用的安全性、调试与性能分析、FreeMarker、Velocity、Ajax,等等。跟随作者一道深入Struts 2,聆听...

    前端HTML模板解析引擎domTemplate.js.zip

    则自定义标签属性不会被浏览器解析,不会破坏原有静态效果,当引入domTemplate脚本,模板引擎回去解析这些标签属性, 并加载数据进行动态渲染。 下图:对比服务器页面渲染和使用domTemplate前端引擎开发流程 ...

    深入浅出Struts 2 .pdf(原书扫描版) part 1

    5.4 textfield、password、hidden标签 63 5.5 submit标签 65 5.6 reset标签 65 5.7 label标签 66 5.8 head标签 66 5.9 textarea标签 66 5.10 checkbox标签 67 5.11 list、listKey和listValue属性 72 5.11.1 赋值一个...

    Struts2 in action中文版

    8.3.1 VelocityResult,也叫做velocity 189 8.3.2 FreemarkerResult,也叫做freemarker 191 8.4 全局结果 192 8.5 小结 193 第四部分 完善应用程序 第9章 集成Spring和Hibernate/JPA 196 9.1 为什么在Struts 2中...

    Thymeleaf中文参考手册_3.0.5版

    Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP .1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的...

    thymeleaf_3.0.5_中文参考手册

    简单说, Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点: 1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在...

    thymeleaf_中文参考手册

    简单说, Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点: 1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在...

    Struts2 国际化字符串 拦截器

    另外,您还可以自定义result类型。 下面让我们来做一个Velocity模板输出的例子,首先在classes/struts.xml中新建一个Action映射(Mapping),将其result类型设为velocity,如以下代码所示: &lt;result type="...

    commons-beanutils-1.8.3 API.chm

    3、为JSP 和XSP创建自定义的标签时 4、在一些XML配置的资源文件中,比如Ant Build脚本、Web应用发布描述符、Tomcat的server.xml文件等。 Java提供了反射机制的APIs(可以参看java.lang.reflect和java.beans ...

Global site tag (gtag.js) - Google Analytics