您的位置:首页 > 其它

velocity模板渲染页面性能优化

2012-06-04 13:10 381 查看

Velocity模板渲染页面性能优化

对于页面性能优化这块,尤其是velocity宏的使用,如何使用宏,怎么样将宏的使用发挥到极致,达到更大的性能的提示,

我的建议如下:

1:一般我们不推荐使用宏,因为宏每次都要要JJT解析,然后才能再执行;

2:使用宏能达到最好的性能情况下,非常安全的,一般在页面有些信息是用户输入的情况

使用会比较好。

下面我针对他的一些意见和我们项目的一些情况,整理了一些关于宏使用的一些技术知识

一:我们如何定义宏和使用宏?

1:定义宏和使用宏

#macro指令用于定义一个VTL模板的重复代码块——宏。下面是一个简单的定义宏的例子:

#macro( d )

<tr><td></td><tr>

#end

这段代码定义了一个宏,名字为d,没有参数。下面是使用这个宏的代码:

#d()

Velocity在遇到#d()的时候,会用"<tr><td></td></tr>"替代上面的#d()这一行。

宏的参数:

宏也可以带参数,而且是任意多个参数。不过,宏定义时有几个参数,宏调用时就要提供同样数目的参数。

#macro( d $name)

<tr><td>$name</td></tr>

#end

#d("name1")

宏的参数可以是以下VTL元素中的任意一种:引用、字符串字面值、数值字面值、整数范围(比如[1 .. 10]、[$start .. $end])、数组、布尔值true或者false。

宏的参数可以是方法,那么下面这个例子,需要特别注意:

#macro(test $a)

$a $a $a

#end

#test($foo.bar())

上面这个例子中,$foo.bar()将会被调用3次,而不是一次。

内联的宏

当宏是在一个Velocity模板中定义时,这个宏(是inline的)只能被该模板使用,同一个网站下的其他模板是不能用的。如果是在一个Velocity宏模板库中定义的宏,就可以被任何同一网站下的模板使用。

和宏有关的一些Velocity属性

velocimacro.library——用逗号分隔的一组文件名,是Velocity宏模板库。默认值是VM_global_library.vm

velocimacro.permissions.allow.inline——宏是否可以在一个普通模板中定义。默认值是false。

velocimacro.permissions.allow.inline.to.replace.global——是否允许模板中的宏覆盖library中的宏。默认值是false。

velocimacro.permissions.allow.inline.local.scope——一个在普通模板中定义的宏,是否允许其他模板使用。默认是false。

velocimacro.context.localscope——在一个宏里通过#set()修改了context,此修改是否仅仅对这个宏自身,而不是永久性修改了context。默认值是false。

velocimacro.library.autoreload——Velocity宏模板库修改之后,是否自动重新加载。默认值是false。debug时可以设置为true,发布时设置为false。

其他一些注意点

宏必须在第一次使用它之前定义。当#Parse()一个模板文件时,尤其要注意这一点。

二: 引入指令和#Stop指令

#Include和#Parse都是用于将本地文件引入当前文件的指令,而且被引入的文件必须位于TEMPLATE_ROOT。这两者之间有一些区别。

#Include

被#Include引入的文件,其内容不会被Velocity引擎解析,所以这些文件应该是静态模板,即不含有VTL的模板。使用#Include()指令时,参数是被双引号括起来的文件名或者是表示文件名的变量。如果有多个文件,以逗号隔开即可。比如#Include("a.gif", "b.html", $file)。

#Parse

#Parse用来在当前模板中引入并执行另一个(本地的)模板——可以是静态的,也可以是动态的——并把结果嵌入到当前位置。#Parse()指令的参数,可以是一个双引号括起来的文件名,也可以是一个变量,但是它不能接受多个参数。

被#Parse引入的文件仍然可以使用#Parse指令。在velocity.properties文件中有一个属性directive.parse.max.depth,默认值是10,它指定了#Parse嵌套的最大层次。既然#Parse嵌套是允许的,#Parse递归也是允许的。

假如a.vm #Parse b.vm,那么a.vm中定义的变量$v,在b.vm中可以随便使用。如果b.vm也定义了$v,那么b.vm中用到的将会是自己的$v,而不是a.vm中的$v。

#Stop

#Stop指令会停止模板引擎的执行,并返回。这在debug中比较有用。

三:#include和#parse到底有什么区别?

parse方法是解析文件,宏是全局方法(调用该方法返回数据),调用方法比较快。

#parse是动态加载的,需要***.vm中的宏定义在 velocity启动的时候就应该得到加载

#include

1.可包含本地文件(不包含VTL)

2.文件内容不经过template engine处理

3.出于安全性的考虑,此文件只能位于TEMPLATE_ROOT目录下

#parse

1.可以引入包含VTL的模板

2.任何模板文件只能位于TEMPLATE_ROOT目录下

比如macro.vm里面添加

#macro (static $src)

$env.getProperties("app.static")/$src

#end

#macro (function_name param_names)

// code...

#end

这样使用 #static("...")方法调用

parse与include的区别在于,若包含的文件中有Velocity脚本标签,将会进一步解析,而include将原样显示。

实例1:

#macro(macroName)#end 脚本函数(宏)调用,不推荐在界面模板中大量使用。

如:在使用EasyJWeb Tools快速生成的添删改查示例中,可以点击列表的标题栏进行升降排序显示,这是我们在EasyJWeb应用中经常看到的一个排序状态显示的模板内容。

函数(宏)定义,一般放在最前面

#macro(orderPic $type)

#if ($orderField.equals($type))

<img src="/images/ico/${orderType}.gif">

#end

#end

具体的调用如:<font color="#FFFFFF">头衔#orderPic("title")</font>

实例2:

包含文件#inclue("模板文件名")或#parse("模板文件名")

主要用于处理具有相同内容的页面,比如每个网站的顶部或尾部内容。

使用方法,可以参考EasyJF开源Blog及EasyJF开源论坛中的应用!

如:#parse("/blog/top.html")或#include("/blog/top.html")

四: Velocity宏使用中需要注意的问题

1、变量输出要带上静止修饰符,避免模板直接空指针报错

举例 :$var错误,$!var正确

如果变量referce与html代码连在一起,需要加上{}

举例 :$! {var}gadsgaggaggas

2、Macro的使用

由于宏存在着安全和性能问题,并且会影响模板的可读性,在模板中不推荐使用宏。

3、变量引用不要加引号,避免重复转义举例:

$stringUtil.equals("$text", "&") 错误

$stringUtil.equals($text, "&") 正确

4、关于velocity的版本

目前推荐使用 velocity 1.6.1,因为以往velocity版本往往会出现向下不兼容的情况 版本升级需要经过架构部门(校长)的充分论证和评估才能实施。

5、Velocity的安全性

为避免VELOCITY页面渲染后产生XSS漏洞,应用应该采用校长的安全方案在应用中引入toolkit-service-velocity.1.5 包。

XSS的过滤,使用velocity提供的xss过滤功能

1)对于html,可以使用 #SHTML($html)2)对于JS,可以用 #SJS($js)

3)对于xml,可以使用#SXML($xml)

4)屏蔽转义,可以使用#SLITERAL()

上述宏,因为非常消耗CPU,因此如果不含特定内容,不到万不得已,不得使用。

五:总结:

1:模块化的东西最好不要放入循环当中,parse或者宏都只是加载一段公共的代码片段而已,循环只是对数据处理来说的;

2:用parse和宏区别不大,parse解析的是一个vm文件,宏返回一段vm代码,优化的过程不是说使用parse或者宏,而是文件或宏里面的数据处理代码,这些代码才有高低效率之分,parse和宏只是在不同场景下不同的使用方法而已。

参考文章:http://people.apache.org/~henning/velocity/html/ch07.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: