一、前言                          

Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力。而且Velocity被移植到不同的平台上,如.Net的 NVelocity和js的Velocity.js,虽然各平台在使用和实现上略有差别,但大部分语法和引擎核心的实现是一致的,因此学习成本降低不少 哦。

最好的学习资源——官网:http://velocity.apache.org/

本系列打算采用如下结构对Velocity进行较为全面的学习,若有不妥或欠缺望大家提出,谢谢。

  1. 入门示例

  2. VTL语法详解

  3. 模板与宿主环境通信

  4. 基础配置项

  5. 深入模板引擎及调优配置

二、模板与宿主环境通信                   

模板指的是使用VTL编写的Velocity模板,宿主环境指的是Java代码调用部分。而两者通信的纽带就是引擎上下文对象( VelocityContext实例 ),下面是常用的 VelocityContext实例 方法。

  1. // 构造函数,入参为上下文的键值对集
  2. VelocityContext(Map context)
  3. // 添加上下文的键值对
  4. Object put(String key, Object value)
  5. // 从上下文获取指定键的值
  6. Object get(String key)
  7. // 检查上下文中是否存在指定的键值对
  8. boolean containsKey(Object key)
  9. // 获取所有键
  10. Object[] getKeys()
  11. // 移除指定键
  12. Object remove(Object key)
  13. // 获取上下文链中邻近的上下文对象
  14. Context getChainedContext()

三、宿主环境向模板传值                    

  1. // 1. 通过构造函数传值
  2. HashMap<String, String> baseCtx = new HashMap<String, String>();
  3. baseCtx.put("version", "");
  4. VelocityContext ctx = new VelocityContext(baseCtx);
  5.  
  6. // 2. 通过put传值
  7. ctx.put("author", "fsjohnhuang");

注意键值对中值的数据类型为

Integer、Long等简单数据类型的装箱类型;

String类型

Object子类

Object[] 数组类型,从1.6开始Velocity将数组类型视为 java.util.List 类型看待,因此模板中可调用 size() 、 get(intindex) 和 isEmpty() 的变量方法;

java.util.Collection子类;

java.util.Map子类;

java.util.Iterator对象;

java.util.Enumeration对象。

除此之外,我们还可以将一个静态类赋予到上下文对象中,如 java.lang.Math静态类

  1. ctx.put("Math", java.lang.Math.class);

四、模板向宿主环境传值                      

  1.  通信示例1——通过引擎上下文对象获取变量

模板文件frm.vm

  1. #set($action="./submit")
  2. <form action="$action">
  3. .........
  4. </form>

Java代码部分

  1. VelocityContext ctx = new VelocityContext();
  2. VelocityEngine ve = new VelocityEngine();
  3. StringWriter sw = new StringWriter();
  4. ve.mergeTemplate("frm.vm", ctx, sw);
  5. String actionStr = ctx.get("action");
  6. System.out.println(actionStr); // 显示./submit

  2.  通信示例2——通过副作用修改变量、属性值

模板文件change.vm

  1. $people.put("john", "john huang")
  2. #set($version = $version + )

Java代码部分

  1. VelocityContext ctx = new VelocityContext();
  2. ctx.put("version", );
  3. HashMap<String, String> people = new HashMap<String,String>();
  4. ctx.put("people", people);
  5. VelocityEngine ve = new VelocityEngine();
  6. StringWriter sw = new StringWriter();
  7. ve.mergeTemplate("change.vm", ctx, sw);
  8. System.out.println(ctx.get("version")); // 显示2
  9. System.out.println(people.get("john")); //显示john huang

上述示例表明在模板中对引用类型实例进行操作时,操作结果将影响到该引用类型实例本身,因此必须谨慎操作。

五、引擎上下文链                          

所谓引擎上下文链就是将原有的上下文对象赋予给新建的上下文对象,从而达到上下文内的键值对复用。具体代码如下:

  1. VelocityContext ctx1 = new VelocityContext();
  2. ctx1.put("name", "fsjohuang");
  3. ctx1.put("version", );
  4. VelocityContext ctx2 = new VelocityContext(ctx1);
  5. ctx2.put("version", );
  6.  
  7. System.out.println(ctx2.get("name")); // 显示fsjohnhuang
  8. System.out.println(ctx2.get("version")); // 显示2

就是当前上下文对象没有该键值对时,则查询上下文链的对象有没有该键值对,有则返回,无则继续找链上的其他上下文对象,直到找到该键值对或遍历完所有链上的上下文对象。

但VelocityContext实例除了put、get方法外,还有remove、getKeys、containsKey方法,它们的行为又是如何的呢?下面我们通过源码来了解吧!

六、从源码看引擎上下文                        

从源码 public class VelocityContext extends AbstractContext implements Cloneable 得知VelocityContext继承自AbstractContext抽象类,且实现了抽象类的internalGet、internalPut、internalContainsKey、internalGetKeys和internalRemove方法,实际开发中常用的put、get等方法却是由AbstractContext提供的,而put、get方法内部在调用对应的internalGet、internalPut方法外再进行了其他处理。这是一种由子类提供具体实现,父类提供对外接口的设计方式(但与纯面向接口编程又有些区别)。

  VelocityContext类源码片段:

  1. public class VelocityContext extends AbstractContext implements Cloneable
  2. {
  3. private Map context = null;
  4.  
  5. public Object internalGet( String key )
  6. {
  7. return context.get( key );
  8. }
  9.  
  10. public Object internalPut( String key, Object value )
  11. {
  12. return context.put( key, value );
  13. }
  14.  
  15. public boolean internalContainsKey(Object key)
  16. {
  17. return context.containsKey( key );
  18. }
  19.  
  20. public Object[] internalGetKeys()
  21. {
  22. return context.keySet().toArray();
  23. }
  24.  
  25. public Object internalRemove(Object key)
  26. {
  27. return context.remove( key );
  28. }
  29. }

从上面可知VelocityContext内置一个Map实例,而各实例方法均为对该Map实例的操作。

AbstractContext类源码片段:

  1. public abstract class AbstractContext extends InternalContextBase
  2. implements Context
  3. {
  4. // 上下文对象链中邻近的上下文对象
  5. private Context innerContext = null;
  6.  
  7. // 只将键值对存放在当前上下文对象的Map对象中
  8. public Object put(String key, Object value)
  9. {
  10. /*
  11. * don't even continue if key is null
  12. */
  13. if (key == null)
  14. {
  15. return null;
  16. }
  17.  
  18. return internalPut(key.intern(), value);
  19. }
  20.  
  21. // 从当前上下文对象的HashMap对象获取键值
  22. // 失败再从上下文链中寻找
  23. public Object get(String key)
  24. {
  25. if (key == null)
  26. {
  27. return null;
  28. }
  29.  
  30. Object o = internalGet( key );
  31.  
  32. if (o == null && innerContext != null)
  33. {
  34. o = innerContext.get( key );
  35. }
  36.  
  37. return o;
  38. }
  39.  
  40. // 搜索整条上下文链的对象是否包含指定键值对
  41. public boolean containsKey(Object key)
  42. {
  43. if (key == null)
  44. {
  45. return false;
  46. }
  47.  
  48. boolean exists = internalContainsKey(key);
  49. if (!exists && innerContext != null)
  50. {
  51. exists = innerContext.containsKey(key);
  52. }
  53.  
  54. return exists;
  55. }
  56.  
  57. // 仅返回当前上下文对象的Map对象的键
  58. public Object[] getKeys()
  59. {
  60. return internalGetKeys();
  61. }
  62.  
  63. // 仅移除当前上下文对象的Map对象指定的键值对
  64. // 上下文链上的其他对象不受影响
  65. public Object remove(Object key)
  66. {
  67. if (key == null)
  68. {
  69. return null;
  70. }
  71.  
  72. return internalRemove(key);
  73. }
  74. }

引擎上下文链就是通过AbstractContext实现的,跟JS的原型链相同。

七、总结                              

本节简单介绍了模板与宿主环境通信的两种方式,并透过源码了解了一下VelocityContext和上下文链的实现,但想继续深入上下文的实现那请自行阅读AbstractContext的父类InternalContextBase了。

尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/4114653.html  ^_^肥仔John

Velocity魔法堂系列三:模板与宿主环境通信的更多相关文章

  1. Velocity魔法堂系列一:入门示例(转)

    Velocity魔法堂系列一:入门示例 一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本 ...

  2. Velocity魔法堂系列二:VTL语法详解

    一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...

  3. Velocity魔法堂系列一:入门示例

    一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...

  4. c/c++ 模板与STL小例子系列<三> traits

    c/c++ 模板与STL小例子系列 traits 对这个概念,还是处于懵逼的状态,初步体会就是,为了解决类型之间的转换问题. 从一个类型为A的指针,转化到类型为B的指针,中间需要用void*来作为中介 ...

  5. WCF入门教程三[WCF的宿主]

    一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...

  6. WCF入门教程系列三

    一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...

  7. 无废话WCF入门教程三[WCF的宿主]

    一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...

  8. 【转】WCF入门教程三[WCF的宿主]

    一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...

  9. 前端魔法堂——异常不仅仅是try/catch

    前言  编程时我们往往拿到的是业务流程正确的业务说明文档或规范,但实际开发中却布满荆棘和例外情况,而这些例外中包含业务用例的例外,也包含技术上的例外.对于业务用例的例外我们别无它法,必须要求实施人员与 ...

随机推荐

  1. SMON功能(二):合并空闲区间

    SMON的作用还包括合并空闲区间(coalesces free extent) 触发场景 早期Oracle采用DMT字典管理表空间,不同于今时今日的LMT本地管理方式,DMT下通过对FET$和UET$ ...

  2. 关于ios中得路径详细讲解

    利用create groups for any added folders 这样的方式表示的是将所有的资源都放在资源包得路径下,没有层次的概念利用create folder references fo ...

  3. 持续集成工具Hudson安装实例

    安装maven 下载maven,解压 [root@localhost local]# pwd /usr/local [root@localhost local]# -bin.tar.gz [root@ ...

  4. 互联网的寒冬来了,BAT都不社招了

    一 总理上次来到创业街,是四个月,要不就是五个月前了. 之后,全国创业形势一路走红,锣鼓喧天鞭炮齐鸣.大众创业万众创新,颇有大炼钢铁亩产万斤之势,尤其在媒体上. 再之后,2015 进入下半年,风投圈的 ...

  5. josephus Problem 中级(使用数组模拟链表,提升效率)

    问题描写叙述: 在<josephus Problem 0基础(使用数组)>中.我们提出了一种最简单直接的解决方式. 可是,细致审视代码之后.发现此种方案的效率并不高,详细体如今.当有人出局 ...

  6. UE4在Android调用Project Tango

    Project Tango应该说是Google一试水AR的设备,其中Project Tango主要二个功能,一个是获取深度信息,如MS的Kinect,有相当多的设备都有这个功能,二是第一人称相对定位, ...

  7. Spring3系列5-Bean的基本用法

    Spring3系列5-Bean的基本用法 本篇讲述了Bean的基本配置方法,以及Spring中怎样运用Bean. 主要内容如下: 一.      Spring中Bean的相互引用 二.      Sp ...

  8. notepad++插件

    html插件 https://github.com/downloads/davegb3/NppTidy2/Tidy2_0.2.zip

  9. 使用过滤器解决SQL注入和跨站点脚本编制

    1 SQL注入.盲注 1.1 SQL注入.盲注概述 Web 应用程序通常在后端使用数据库,以与企业数据仓库交互.查询数据库事实上的标准语言是 SQL(各大数据库供应商都有自己的不同版本).Web 应用 ...

  10. WebDriver基本API使用手册(基于Java和C#)

    WebDriver基本API使用手册(基于Java和C#) http://www.docin.com/p-747728551.html