Velocity魔法堂系列三:模板与宿主环境通信
一、前言
Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力。而且Velocity被移植到不同的平台上,如.Net的 NVelocity和js的Velocity.js,虽然各平台在使用和实现上略有差别,但大部分语法和引擎核心的实现是一致的,因此学习成本降低不少 哦。
最好的学习资源——官网:http://velocity.apache.org/
本系列打算采用如下结构对Velocity进行较为全面的学习,若有不妥或欠缺望大家提出,谢谢。
3. 模板与宿主环境通信
4. 基础配置项
5. 深入模板引擎及调优配置
二、模板与宿主环境通信
模板指的是使用VTL编写的Velocity模板,宿主环境指的是Java代码调用部分。而两者通信的纽带就是引擎上下文对象( VelocityContext实例 ),下面是常用的 VelocityContext实例 方法。
// 构造函数,入参为上下文的键值对集
VelocityContext(Map context)
// 添加上下文的键值对
Object put(String key, Object value)
// 从上下文获取指定键的值
Object get(String key)
// 检查上下文中是否存在指定的键值对
boolean containsKey(Object key)
// 获取所有键
Object[] getKeys()
// 移除指定键
Object remove(Object key)
// 获取上下文链中邻近的上下文对象
Context getChainedContext()
三、宿主环境向模板传值
// 1. 通过构造函数传值
HashMap<String, String> baseCtx = new HashMap<String, String>();
baseCtx.put("version", "");
VelocityContext ctx = new VelocityContext(baseCtx); // 2. 通过put传值
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静态类
ctx.put("Math", java.lang.Math.class);
四、模板向宿主环境传值
1. 通信示例1——通过引擎上下文对象获取变量
模板文件frm.vm
#set($action="./submit")
<form action="$action">
.........
</form>
Java代码部分
VelocityContext ctx = new VelocityContext();
VelocityEngine ve = new VelocityEngine();
StringWriter sw = new StringWriter();
ve.mergeTemplate("frm.vm", ctx, sw);
String actionStr = ctx.get("action");
System.out.println(actionStr); // 显示./submit
2. 通信示例2——通过副作用修改变量、属性值
模板文件change.vm
$people.put("john", "john huang")
#set($version = $version + )
Java代码部分
VelocityContext ctx = new VelocityContext();
ctx.put("version", );
HashMap<String, String> people = new HashMap<String,String>();
ctx.put("people", people);
VelocityEngine ve = new VelocityEngine();
StringWriter sw = new StringWriter();
ve.mergeTemplate("change.vm", ctx, sw);
System.out.println(ctx.get("version")); // 显示2
System.out.println(people.get("john")); //显示john huang
上述示例表明在模板中对引用类型实例进行操作时,操作结果将影响到该引用类型实例本身,因此必须谨慎操作。
五、引擎上下文链
所谓引擎上下文链就是将原有的上下文对象赋予给新建的上下文对象,从而达到上下文内的键值对复用。具体代码如下:
VelocityContext ctx1 = new VelocityContext();
ctx1.put("name", "fsjohuang");
ctx1.put("version", );
VelocityContext ctx2 = new VelocityContext(ctx1);
ctx2.put("version", ); System.out.println(ctx2.get("name")); // 显示fsjohnhuang
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类源码片段:
public class VelocityContext extends AbstractContext implements Cloneable
{
private Map context = null; public Object internalGet( String key )
{
return context.get( key );
} public Object internalPut( String key, Object value )
{
return context.put( key, value );
} public boolean internalContainsKey(Object key)
{
return context.containsKey( key );
} public Object[] internalGetKeys()
{
return context.keySet().toArray();
} public Object internalRemove(Object key)
{
return context.remove( key );
}
}
从上面可知VelocityContext内置一个Map实例,而各实例方法均为对该Map实例的操作。
AbstractContext类源码片段:
public abstract class AbstractContext extends InternalContextBase
implements Context
{
// 上下文对象链中邻近的上下文对象
private Context innerContext = null; // 只将键值对存放在当前上下文对象的Map对象中
public Object put(String key, Object value)
{
/*
* don't even continue if key is null
*/
if (key == null)
{
return null;
} return internalPut(key.intern(), value);
} // 从当前上下文对象的HashMap对象获取键值
// 失败再从上下文链中寻找
public Object get(String key)
{
if (key == null)
{
return null;
} Object o = internalGet( key ); if (o == null && innerContext != null)
{
o = innerContext.get( key );
} return o;
} // 搜索整条上下文链的对象是否包含指定键值对
public boolean containsKey(Object key)
{
if (key == null)
{
return false;
} boolean exists = internalContainsKey(key);
if (!exists && innerContext != null)
{
exists = innerContext.containsKey(key);
} return exists;
} // 仅返回当前上下文对象的Map对象的键
public Object[] getKeys()
{
return internalGetKeys();
} // 仅移除当前上下文对象的Map对象指定的键值对
// 上下文链上的其他对象不受影响
public Object remove(Object key)
{
if (key == null)
{
return null;
} return internalRemove(key);
}
}
引擎上下文链就是通过AbstractContext实现的,跟JS的原型链相同。
七、总结
本节简单介绍了模板与宿主环境通信的两种方式,并透过源码了解了一下VelocityContext和上下文链的实现,但想继续深入上下文的实现那请自行阅读AbstractContext的父类InternalContextBase了。
尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/4114653.html ^_^肥仔John
Velocity魔法堂系列三:模板与宿主环境通信的更多相关文章
- Velocity魔法堂系列一:入门示例(转)
Velocity魔法堂系列一:入门示例 一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本 ...
- Velocity魔法堂系列二:VTL语法详解
一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...
- Velocity魔法堂系列一:入门示例
一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...
- c/c++ 模板与STL小例子系列<三> traits
c/c++ 模板与STL小例子系列 traits 对这个概念,还是处于懵逼的状态,初步体会就是,为了解决类型之间的转换问题. 从一个类型为A的指针,转化到类型为B的指针,中间需要用void*来作为中介 ...
- WCF入门教程三[WCF的宿主]
一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...
- WCF入门教程系列三
一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...
- 无废话WCF入门教程三[WCF的宿主]
一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...
- 【转】WCF入门教程三[WCF的宿主]
一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...
- 前端魔法堂——异常不仅仅是try/catch
前言 编程时我们往往拿到的是业务流程正确的业务说明文档或规范,但实际开发中却布满荆棘和例外情况,而这些例外中包含业务用例的例外,也包含技术上的例外.对于业务用例的例外我们别无它法,必须要求实施人员与 ...
随机推荐
- WHY数学图形可视化工具(开源)
WHY数学图形可视化工具 软件下载地址:http://files.cnblogs.com/WhyEngine/WhyMathGraph.zip 源码下载地址: http://pan.baidu.com ...
- 谢谢博客-园,让我不再有开源AYUI的想法
第一次 第二次 教程不会在博客园上写了,具体的看我官网博客吧,谢谢大家了 ================= 我是个有素质的程序员 艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹 ...
- ASP.NET MVC学习系列(二)-WebAPI请求
继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用Jquery 来发起异步请求实现 ...
- Android学习之ProgressBar
ProgressBar用于向用户显示某个耗时操作完成的百分比,避免长时间执行某个耗时操作时让用户感觉程序失去了响应,从而提高用户界面的友好性. 请看下面的界面布局: <LinearLayout ...
- Java 部分排序算法
. import java.io.*;import java.math.*;import java.util.*;public class Algr{ public static int array[ ...
- nlog(n)解动态规划--最长上升子序列(Longest increasing subsequence)
最长上升子序列LIS问题属于动态规划的初级问题,用纯动态规划的方法来求解的时间复杂度是O(n^2).但是如果加上二叉搜索的方法,那么时间复杂度可以降到nlog(n). 具体分析参考:http://b ...
- Openvswitch原理与代码分析(5): 内核中的流表flow table操作
当一个数据包到达网卡的时候,首先要经过内核Openvswitch.ko,流表Flow Table在内核中有一份,通过key查找内核中的flow table,即可以得到action,然后执行acti ...
- iOS10 CoreData新特性
原文地址:What's New in Core Data in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0 翻译者:肖品,原创文章转载请著名出处 ...
- 在spring,mybatis整合配置中走的弯路(1)
在接触一个新东西,总免不了走一些弯路,也正是在这些弯路中,我们不断的成长. 从git上把之前写的代码扒下来,看看我在当初使用spring与mybatis中所走的弯路,路过的君子也可引以为戒. < ...
- 解决CSS移动端1px边框问题
移动项目开发中,安卓或者IOS等高分辨率屏幕会把1px的border渲染成2px来显示,网上搜了一下,解决方法如下: 一.利用css中的transform的缩放属性解决,推荐这个.如下面代码. < ...