Velocity官方指南-容器

原文网址  译者:曾道涛

简介
“容器”这一概念对于Velocity来说很重要,它是在系统的各部分之间传递一系列数据的通用技术。也就是说,容器是Java层(或者程序员)和模板层(或者设计师)之间的数据搬运工。作为程序员,你会收集各种类型的对象,包括所有你程序需要的,然后把它们放在容器里。对于设计师来说,这些对象,以及它们的方法和属性,可以通过被称为引用的模板元素来访问。一般来说,你会和设计师一起决定应用程序的数据需求。从某种意义上说,一旦你为设计师生成了一个数据集,也即在模板中提供了“API”访问。因此,在这个阶段的开发过程中,你值得花时间仔细分析。

虽然Velocity允许你创建自己的容器类来满足特殊的需求和技术(比如像一个直接访问LDAP服务器的容器),一个叫VelocityContext的基本实现类已经作为发行版的一部分提供给你。

VelocityContext适合所有的一般需求,所以我们强烈推荐你使用它。只有在特殊情况和高级应用中,才需要你扩展或者创建你自己的容器实现。

使用VelocityContext就像使用一个普通的Java Hashtable类一样简单。虽然接口包含其他有用的方法,我们使用的两个主要方法是:

public Object put(String key, Object value);
public Object get(String key);

请注意,参数value必须继承自java.lang.Object。基本类型像int和float必须用合适的包装类包装。
这就是所有关于容器的基本操作。如需更多信息,可以查看发行版中包含的API文档。

 

for和foreach()遍历对象的支持

作为一个程序员,对于你放在容器中的对象有很大的自主权。但是正如大多数自主权,这也需要一点点责任,所以要理解Velocity支持什么,以及任何可能出现的问题。Velocity支持几种集合类型在VTL中使用foreach()语句。
•  Object []   普通对象数组,在这里无需多说。如果一个类中提供了迭代器接口,Velocity会自动包装你的数组,但是这不应该涉及到程序员和模板的设计者。更有趣的是,Velocity现在允许模板设计者把数组当作定长链表来处理(Velocity 1.6中就是这样)。这意味着他们既可以在数组上也可以在java.util.List的实例上调用像size(), isEmpty()和get(int)这样的方法,而无需关心它们本身的差异。
•  java.util.Collection  Velocity通过iterator()方法返回一个迭代器在循环中使用,所以如果你正在你的对象上实现一个集合接口,请确保iterator()方法返回一个有效的迭代器。
•  java.util.Map    这里,Velocity通过接口的values()方法返回一个Collection接口,iterator()方法在它上面调用来检索用于循环的迭代器。
•  java.util.Iterator   使用的时候需要注意:目前只是暂时支持,关注的问题是迭代器不能重置。如果一个未初始化的迭代器被放进了容器,并且在多个foreach()语句中使用,如果第一个foreach()失败了,后面的都会被阻塞,因为迭代器不会重启。
•  java.util.Enumeration     使用的时候需要注意:和java.util.Iterator一样,目前只是暂时支持,关注的问题是枚举不能重置。如果一个未初始化的枚举被放进了容器,并且在多个foreach()语句中使用,如果第一个foreach()失败了,后面的都会被阻塞,因为枚举不会重启。

•  任何拥有public Iterator iterator()方法的公有类永远不会返回null。Velocity会把寻找一个iterator()方法作为最后的手段。这提供了很大的灵活性,也自动支持Java 1.5中的java.util.Iterable接口。

对于Iterator和Enumeration,推荐只有在万不得已的情况下才把它们放进容器,你也应该尽可能地让Velocity找到合适的、可复用的迭代接口。

虽然有充足的理由直接使用java.util.Iterator接口(比如像JDBC这样的大数据集),但是如果能够避免,用其他的可能会更好。“直接”是说像下面这样:

Vector v = new Vector();
v.addElement("Hello");
v.addElement("There");

context.put("words", v.iterator() );

当迭代器本身被放进了容器。当然,你也可以简单地这样做:

context.put("words", v );

两种方式都可以:Velocity能够识别实现了Collection(像List)接口的Vector,并因此找到iterator()方法,在它每次需要的时候调用iterator()来刷新迭代器。一旦Velocity在foreach()中使用了一个空迭代器(先跳过这里…),Velocity没办法为它正在使用的下一个foreach()获取一个新的迭代器。结果是后面任何使用空迭代器引用的foreach()都会阻塞,并且没有输出。

上面这些并不是为了表明在Velocity中遍历集合需要十分小心。恰恰相反,一般来说,只要在你向容器中添加迭代器时小心就可以了。

对静态类的支持
并非所有的类都可以实例化。像java.lang.Math这样的类不提供任何公有的构造函数,但是它包含了有用的静态方法。为了从模板中访问这些静态方法,你可以简单地把这些类自身添加到容器中:

context.put("Math", Math.class);

这样你就可以在模板中用$Math引用调用java.lang.Math中的任何公有静态方法。

容器链

Velocity容器设计的一大创新特性是容器链的概念。有时也被称为contextwrapping,这个高级特性允许你以一种方式把独立的容器连接在一起,使它们对模板来说像一个连续的容器。

最好用一个例子来说明:

VelocityContext context1 = new VelocityContext();

context1.put("name","Velocity");
context1.put("project", "Jakarta");
context1.put("duplicate", "I am in context1");

VelocityContext context2 = new VelocityContext( context1 );

context2.put("lang", "Java" );
context2.put("duplicate", "I am in context2");

template.merge( context2, writer );

在上面这段代码中,我们创建context2,使它连接context1。这意味着在模板中,你可以访问这两个VelocityContext对象中放置的任意项,只要在添加对象的时候没有重复的键。如果遇到这种情况,就像上面的键”duplicate”,最近的容器中存储的对象可以被访问。在上面这个例子中,返回的对象是字符串”I am in context2″。

注意,这种容器中对象的重复或者“覆盖”,不会以任何方式损坏或者修改被覆盖的对象。所以在上面的例子中, 字符串”I am in context1″还存在并且完好无损,仍然可以通过context1.get(“duplicate”)访问。但是在上面的例子中,模板中引用”$duplicate”的值会是”I am in context2″,模板不能访问被覆盖的字符串”I am in context1″。

也要注意,当你使用模板向一个渲染之后再检查的容器中添加信息的时候,你必须要小心。在一个模板中,通过set()语句改变容器只会影响外层的容器。所以在期望模板中的数据已经被添加到内部容器时,请确保你没有丢弃外层的容器。

这个特性有很多用途,目前最常用的就是提供层次数据访问和工具箱。

就像前面提到过的,Velocity容器机制是可以扩展的,但是超出了本指南的当前范围。如果你有兴趣,可以查看包org.apache.velocity.context中的类,看看提供的容器怎么组合在一起。更进一步,有几个例子在发行版的examples/context_example目录下,它们展示了可能的实现,包括一个使用数据库作为后台存储的例子。

请注意,这些例子不被支持,它们仅仅是出于示范和教学目的。

模板中创建的对象
在模板中,有两种情况Java代码必须处理运行时创建的对象:

当模板设计者通过Java代码调用容器中放置的对象的方法:
#set($myarr = [“a”,”b”,”c”] )
$foo.bar( $myarr )

当模板向容器中添加对象,Java代码可以在合并过程完成后访问这些对象:
#set($myarr = [“a”,”b”,”c”] )
#set( $foo = 1 )
#set( $bar = “bar”)

如果非常直接地处理这些情况,有几个事情需要知道:
•  当放在容器中或者传给方法时,VTL RangeOperator [ 1..10 ]和ObjectArray [“a”,”b”]是java.util.ArrayList对象。所以,当你设计接受模板中创建的数组的方法时,你应该牢记这个问题。
•  VTL Map引用毫无疑问是用java.util.Map存储的。
•  小数在容器中会是Doubles或者BigDecimals,整数会是 Integer, Long,或者BigIntegers字符串当然还是Strings。
•  Velocity在调用方法时会适当地省略参数,所以调用setFoo( int i )把一个整数放入容器,#set()和它等价。

其他容器问题
VelocityContext(或者任何派生自AbstractContext的Context)提供的一个特性是节点特有的自我监视缓存。一般来说,作为一个开发者,当你使用VelocityContext作为你的容器时,不必担心这些。但是,有一个目前已知的使用模式,你必须知道这个特性。

当VelocityContex访问模板中的节点时,它会收集关于这些有序节点的自我监视信息。所以,在下面这几种情况:
•  你使用同一个VelocityContext对象遍历同样的模板。
•  模板缓存关闭。
•  在每次迭代中,你通过getTemplate()请求模板。

你的VelocityContext有可能出现内存泄露(在收集更多自我监视信息时真会出现)。真正发生的是,它为每个它访问的模板收集模板节点的自我监视信息,当模板缓存关闭时,对VelocityContext来说它每次都是访问一个新模板。因此,它收集更多的自我监视信息,并且一直增长。强烈推荐你做以下一条或者更多条:

•  通过模板补偿处理,每次遍历都新建一个VelocityContext。这样就不会收集自我监视缓存数据。在你由于VelocityContext已经填充了数据或对象而想重用它的情况下,你可以简单地把填充好的VelocityContext包装成另一个VelocityContext,外层的那个会收集自我监视信息,你直接丢弃就可以了。例如 VelocityContext useThis = new VelocityContext( populatedVC );它可以很好地工作,因为外层的容器会存储自我监视缓存数据,它可以从内部容器获取任何请求的数据(当它为空时)。你仍然要注意,如果你的模板把数据放入容器并且期待后面的遍历使用这些数据,你需要做另外一个准备,因为任何模板set()语句会被存储在最外层的容器。看“Context chaining”章节中的讨论来获取更多信息。
•  打开模板缓存。这样可以避免在每次遍历中重复解析模板,因此VelocityContext不仅可以避免增加自我监视的缓存信息,还可以带来性能的提升。
•  在循环遍历的过程中重用模板对象。如果缓存关闭了,你不必让Velocity一遍又一遍地重复读取和解析相同的模板,所以VelocityContext就不会每次都收集新的自我监视信息。 

时间: 2024-10-03 17:02:32

Velocity官方指南-容器的相关文章

【Velocity官方指南】使用单例模式还是非单例模式

译者:大胃  原文链接 从Velocity 1.2以后的版本,开发者对于Velocity引擎的使用有了两种方式,单例模型(Singleton)以及多个独立实例模型.Velocity的核心部分也采用了这两种模型,目的是为了让Velocity可以更容易与你的JAVA应用相集成. 单例模式(Singleton): 这是一个遗留(Legacy)模式,在这种模式下只有一个Velocity的引擎在JVM(或者是WEB容器,这取决于你的环境)中会被实例化,同时被全部程序所共享.这对本地化的配置以及可被分享的其

Apache Velocity官方指南-资源

原文地址 对于程序员来说,这里有相当多的资源和示例可以获取到.我们推荐你查看我们的示例.文档甚至源代码.以下便是一些很好的途径: 用户和开发者社区:  通过此页加入我们. 从此页还可以获取到邮件列表的历史档案. 维基百科:  http://wiki.apache.org/velocity/ . Velocity的维基中包含了文章.样例代码和其他写作社区的精华内容. Frequently Asked Questions (FAQ):  http://wiki.apache.org/velocity

Velocity官方指南-使用Velocity

原文地址  译者:冷风  校对:方腾飞 如果你使用的是VelocityViewServlet或者其他的web框架,你不会直接调用到Velocity.但是,如果在非web的应用中或者自己编写的web框架时,你将会像上面说的基本流程一样直接调用到Velocity 引擎.另外一个需要记住的重点是,必须在使用Velocity合并模版之前,初始化Velocity引擎. Velocity辅助类 Velocity中包含一个叫做Velocity( org.apache.velocity.app.Velocity

Velocity官方指南-简介

简介 Velocity是基于Java开发的模板引擎,一款简单而强大的开发工具,可以方便的按照格式创建.渲染文档和显示数据.在本指南中,我们希望能够对使用Velocity开发的基本知识做一个概述. 使用Velocity构建Web应用 Velocity通常被用于构建Web应用程序,想要在Web应用中使用Velocity,还需要一个servlet或以servlet为基础的框架.最直接的方法就是使用VelocityViewServlet(在Velocity Tools子项目中),也可以使用许多第三方框架

Apache Velocity官方指南-总结

总结 我们希望这份简洁的指南是一个有用的介绍为了使用Velocity在你的Java工程中,并且感谢你对Velocity感兴趣,对于这个文档和Velocity模版引擎它自身我们欢迎任何评论. 请提交详细的,富有想法的和建设性的反馈通过我们的邮件列表. 转载自 并发编程网 - ifeve.com

Velocity官方指南-Velocity是如何工作的

基本模式 当你在一个应用程序或者一个servlet里,或者在其他任何一个地方使用Velocity时,通常按照如下方式处理: 初始化Velocity.Velocity可以使用两种模式,作为"单独的运行时实例"的单例模式(在下面的内容会介绍),你仅仅只需要初始化一次. 创建一个Context对象(后面会介绍这是什么). 把你的数据对象添加到Context(上下文). 选择一个模板. '合并' 模板和你的数据输出. 在代码里通过org.apache.velocity.app.Velocity

Apache Velocity官方指南-12.模板编码及国际化

Velocity允许你指定模板的字符集编码,并且非常简单.常用的resource API已经支持把编码作为入参.代码如下: org.apache.velocity.app.Velocity: public static Template getTemplate(String name, String encoding) public static boolean mergeTemplate( String templateName, String encoding, Context contex

《Apache Velocity开发者指南》

欢迎各位光临并发编程网,并发网最近几年一直致力于翻译优秀的技术文章,从未间断,并发网从本月开始计划组织翻译各个技术框架的官方指南,本月组织翻译Apache Velocity官方指南.Velocity是在阿里巴巴和支付宝等公司被广泛使用的一种基于Java的模板引擎,有兴趣翻译的同学请在评论中回复翻译章节和完成时间,翻译完之后提交到并发编程网,网站使用指南请参考:如何投稿. 简介 资源 Velocity是如何工作的 使用单例还是非单例模式 容器 在应用程序中使用Velocity 应用程序中的属性 C

ExtJS 4 官方指南翻译:容器与布局(Layouts and Containers)

原文:http://docs.sencha.com/ext-js/4-0/#!/guide/layouts_and_containers 翻译:frank/sp42 转载请保留本页信息 布局系统是 Ext JS 的最强大的部分之一.它可以处理您的应用程序中的每个组件的大小和定位.本指南介绍了如何进行布局的基础知识. The layout system is one of the most powerful parts of Ext JS. It handles the sizing and po