Velocity简明教程
1.1什么是Velocity?
Velocity在Apache官网地址:http://velocity.apache.org/
Velocity是一个基于Java的模板引擎。它允许任何人使用简单而强大的模板语言来引用Java代码中定义的对象。
当Velocity用于Web开发时,Web设计人员可以与Java程序员并行工作,来根据模型 - 视图 - 控制器(MVC)模型开发Web站点,这意味着网页设计人员可以专注于创建一个看起来很好的站点,程序员可以专注于编写代码。Velocity将Java代码与网页分开,使网站在其生命周期内更加可维护,并为JSP或PHP提供了可行的替代方案。
Velocity的功能远远超出了Web的范围; 例如,它可以用于从模板生成SQL,PostScript和XML。它可以作为独立实用程序生成源代码和报告(report),也可以用作其他系统的集成组件。Velocity支持为各种Web框架提供模板服务,使他们能够根据真正的MVC模型促进促进Web应用程序的开发。
1.2.VeloCity提供的主要功能
1.Web 应用:开发者在不使用 JSP 的情况下,可以用 Velocity 让 HTML 具有动态内容的特性。(这是主要学习内容,其他只供了解)
\2. 源代码生成:Velocity 可以被用来生成 Java 代码、SQL 或者 PostScript。有很多开源和商业开发的软件是使用 Velocity 来开发的(有兴趣的可以尝试玩一下)。
\3. 自动 Email:很多软件的用户注册、密码提醒或者报表都是使用 Velocity 来自动生成的。使用 Velocity 可以在文本文件里面生成邮件内容,而不是在 Java 代码中拼接字符串。
\4. 转换 xml:Velocity 提供一个叫 Anakia 的 ant 任务,可以读取 XML 文件并让它能够被 Velocity 模板读取。一个比较普遍的应用是将 xdoc 文档转换成带样式的 HTML 文件。
2.1.VoleCity HelloWord
我们主要学习的是如何使用Velocity作为模板引擎替换jsp在web项目中作为页面载体的作用,那么必然涉及到控制层与视图层的数据交互问题。比如说,controller(或Servlet)中setAttribute/getAttribute,Velocity页面如何接收属性值,如何set属性值。
Velocity中提供了能替代El表达式与Jstl标签的一套语法,在velocity页面中主要使用这套语法接传值,之后会有语法知识的简介。Spring framework对Velocity提供了支持,有对应的VelocityViewResolver,我们在Controller方法中返回结果字符串就可以响应velocity页面。
先看一个简单的示例,模拟请求Servlet,service方法中set属性值,在velocity页面中接收值。
~~~java
//VelocityViewServlet是velocity提供的Servlet,主要处理请求的方法是handleRequest,参数位置提供了Context类型的对象,它是velocity的容器,负责传递数据。
public class MyServlet extends VelocityViewServlet {
@Override
protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) {
//分别往context,request中设置4个属性值;测试velocity页面可以以什么方式接到。
context.put("name", "zhangsan");
request.setAttribute("name1","lisi");
context.put("name2","wangwu");
request.setAttribute("name3","zhaoliu");
return this.getTemplate("index.vm");
}
}
~~~
velocity的页面以vm为后缀:
~~~velocity
name is $name
name1 is $name1
name2 is ${name2}
name2 is ${name3}
~~~
运行结果:
~~~properties
name is zhangsan
name1 is lisi
name2 is wangwu
name2 is zhaoliu
~~~
从运行结果可以看出,request和context的属性值都可以通过velocity语法取值(${name}也是Velocity的语法)。context的作用域低于Request。
通过配置velocity.properties文件,可以自定义vm文件加载方式,指定编码等。当然,也可以不配置velocity.properties,使用缺省的值即可。
~~~properties
设置模板文件加载器,webapp从应用根目录加载
resource.loader = webapp
webapp.resource.loader.class = org.apache.velocity.tools.view.WebappResourceLoader
模板路径,根目录下的vm文件夹
webapp.resource.loader.path = /vm
设置编码
input.encoding = UTF-8
output.encoding = UTF-8
~~~
velocity本身具有多重的功能,但是我们对它的使用目前仅限于作为前端页面模板,它相比jsp强大的一点是提供了一套交单的语法,完全可以取代jstl标签,这套模板语言语法比c标签简单,而且可读性更强,维护更方便。
3.1.Velocity模板语言
velocity的功能也比较强大,这里主要选择一些常用的语法。同时可以比较同样的功能,用jstl标签与模板语言实现起来的区别。在 之前例子的页面中可以看到很多以 # 和$符开头的内容,这些都是 Velocity 的语法。在 Velocity
中所有的关键字都是以 # 开头的,而所有的变量则是以$开头。Velocity 的语法类似于 JSP 中的
JSTL,甚至可以定义类似于函数的宏,下面来看看具体的语法规则。
一、变量
和我们所熟知的其他编程语言一样,Velocity 也可以在模板文件中有变量的概念。
\1. 变量定义
~~~velocity
set($name =“velocity”)
~~~
等号后面的字符串将被 Velocity 引擎重新解析,例如出现以$开始的字符串时,将做变量的替换。
~~~velocity
set( hello=“hello name”)
上面的这个等式将会给$hello 赋值为“hello velocity”
~~~
\2. 变量的使用
~~~velocity
在模板文件中使用
name,
{name}使用定义的变量。推荐使用
name这种格式,因为在模板中同时可能定义了类似
name 和
names的两个变量,如果不选用大括号的话,引擎就没有办法正确识别
names 这个变量。
对于一个复杂对象类型的变量,例如
person,可以使用
{person.name} 来访问 person 的 name 属性。值得注意的是,这里的{person.name} 并不是直接访问 person 的 name 属性,而是访问 person 的 getName() 方法,所以{person.name} 和${person.getName()} 是一样的。
~~~
\3. 变量赋值
在第一小点中,定义了一个变量,同时给这个变量赋了值。对于 Velocity 来说,变量是弱数据类型的,可以在赋了一个 String 给变量之后再赋一个数字或者数组给它。可以将以下六种数据类型赋给一个 Velocity 变量:变量引用, 字面字符串, 属性引用, 方法引用, 字面数字, 数组列表。
~~~velocity
set( foo= bar)
set($foo =”hello”)
set( foo.name= bar.name)
set( foo.name= bar.getName($arg))
set($foo = 123)
set( foo=["foo", bar])
~~~
二、循环
在 Velocity 中循环语句的语法结构如下:
~~~velocity
foreach( elementin list)
This is element velocityCount
end
~~~
Velocity 引擎会将 list 中的值循环赋给 element 变量,同时会创建一个$velocityCount 的变量作为计数,从 1 开始,每次循环都会加 1。
三、条件语句
条件语句的语法如下
~~~velocity
if(condition)
…
elseif(condition)
…
else
…
end
~~~
四、关系操作符
Velocity 引擎提供了 AND、OR 和 NOT 操作符,分别对应&&、||和! 例如:
~~~velocity
if(foo &&bar)
end
~~~
五、宏
Velocity 中的宏可以理解为函数定义。定义的语法如下:
~~~velocity
macro(macroName arg1 arg2 …)
…
end
~~~
调用这个宏的语法是:
~~~velocity
macroName(arg1 arg2 …)
~~~
这里的参数之间使用空格隔开,下面是定义和使用 Velocity 宏的例子:
~~~velocity
macro(sayHello $name)
hello $name
end
调用:
sayHello(“velocity”)
输出的结果为 hello velocity
~~~
六、#parse 和 #include
#parse 和 #include 指令的功能都是在外部引用文件,而两者的区别是,#parse 会将引用的内容当成类似于源码文件,会将内容在引入的地方进行解析,#include 是将引入文件当成资源文件,会将引入内容原封不动地以文本输出。分别看以下例子:
foo.vm 文件中定义:
~~~velocity
set($name =“velocity”)
~~~
在parse.vm中执行#parse:
~~~velocity
parse(“foo.vm”)
输出结果为:velocity
~~~
在include.vm文件中执行#include:
~~~velocity
include(“foo.vm”)
输出结果为:#set($name =“velocity”)
~~~
以上内容包含了部分 Velocity 的语法,详细的语法内容可以参考 Velocity 的官方文档。
4.1.Spring MVC 对 Velocity 的支持
spring framework同时支持Velocity与FreeMarker,但是Velocity已经6年未更新,所以推荐使用FreeMarker。
1.添加依赖:velocity需要1.0以上版本
~xml
org.apache.velocity
velocity
1.6
org.apache.velocity
velocity-tools
2.0
org.springframework
spring-context-support
4.2.5.RELEASE
~
2.上下文配置,在Spring-mvc配置文件中
~~~xml
~~~
3.创建模板(也就是.vm文件)
模板需要存储在Configurer bean指定路径下(也就是上面配置的velocityConfig中resourceLoaderPath指定的路径下)。
可以看到velocity的视图解析器与jsp的InternalResourceViewResolver配置方式基本一样,可以猜到controller方法中返回的结果字符串或者ModelAndView中的路径形式也与之前完全一样。比如,如果控制器返回一个包含视图名为“welcome”的ModelAndView对象,则解析器将根据需要查找/WEB-INF/velocity/welcome.vm模板。
4.高级配置
以上配置可以满足一般需求,如果还有其他配置需求,我们可以采用这种配置方式。
引入属性文件,在properties文件中定义配置项。这种配置方式是可选的,但如果指定,则需要指定则需要把值传给velocity以便velocity自行初始化。 那么如何传给velocity呢,在上面的VelocityConfigurer bean定义中指定属性文件的位置。
~xml
~
当然,也可以以内联的方式,直接在viewConfig中配置属性。比如
~xml
file
org.apache.velocity.runtime.resource.loader.FileResourceLoader
${webapp.root}/WEB-INF/velocity
false
~
具体配置那些属性,在第一个例子中有一些,还有其他的请自行查阅吧。