Velocity基础及使用

概念

velocity是apache的子项目,官网http://velocity.apache.org/,类似于freemarker和jsp,是模板语言。

 

基本配置:

web工程中:

1、引入jar包:

2、web.xml配置:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">

<display-name>velocity_web_test</display-name>

<servlet>

<servlet-name>velocityView</servlet-name>

<servlet-class>org.apache.velocity.tools.view.VelocityViewServlet</servlet-class>

<load-on-startup>10</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>velocityView</servlet-name>

<url-pattern>*.vm</url-pattern>

</servlet-mapping>

</web-app>

其中配置了velocity的VelocityViewServlet,拦截*.vm请求。

 

3、写一个vm文件,如test.vm

<html>

    <head></head>

      

<body>

<table>

 

#set( $treeList = ["pine", "oak", "maple", "redwood"])

<tr><td>Tree Name</td></tr>

#foreach ($name in $treeList)

<tr>

<td>

<b><font color="GREEN">$name</font></b> is a big tree!

</td>

</tr>

#end

 

    </table>

 

</body>

</html>

 

访问结果:

表示已经成功。

 

velocity使用的语言成为VTL语言,类似于freemark的ftl。

servlet中使用velocity配置:

只用在自己的servlet中继承基本配置中的VelocityViewServlet即可:

如:

VelocityServlet.java:

package com.test;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.velocity.Template;

import org.apache.velocity.context.Context;

import org.apache.velocity.tools.view.VelocityViewServlet;

 

/**

* 测试velocityservlet

*/

public class VelocityServlet extends VelocityViewServlet {

    private static final long serialVersionUID = 1L;

 

    @Override

    protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) {

        ctx.put("username", "anders");

        return getTemplate("test.vm");

 

    }

 

    @Override

    protected void setContentType(HttpServletRequest request, HttpServletResponse response) {

        response.setContentType("text/html;charset=utf-8");

    }

}

然后web.xml配置servlet:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns="http://java.sun.com/xml/ns/javaee"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

    id="WebApp_ID" version="2.5">

    <display-name>velocity_web_test</display-name>

    <servlet>

        <servlet-name>VelocityServlet</servlet-name>

        <servlet-class>com.test.VelocityServlet</servlet-class>

    </servlet>

    <servlet-mapping>

        <servlet-name>VelocityServlet</servlet-name>

        <url-pattern>/VelocityServlet</url-pattern>

    </servlet-mapping>

</web-app>

 

test.vm:

<html>

    <head></head>

<body>

     hello,$username

</body>

</html>

 

访问servlet(注意不要直接访问vm),如:http://localhost/velocity_web_test/VelocityServlet

显示:

hello, anders

在servlet的handleRequest方法中即可为vm页面设置需要显示的变量

 

 

基本用法

设置变量,取变量

#set($a="abc")

     hello,$a

显示

hello,abc

 

#后面一般接命令,$后面一般接变量

#set($a="abc")表示设置变量a为abc字符串

$a表示显示变量a的值,所以就是:hello,abc

 

例子:

$data.setUser("jon")

##等同于

#set( $data.User = "jon" )

注释

单行注释:

 

## 单行注释

 

多行注释:

#*

多行1

多行2

*#

 

取值的方式

取值也叫作引用。

变量命名规则:字母开头,后面可以是字母、数字、下划线、中划线

取值跟jstl类似,如:

${username}

${user.userName}

还可以直接执行java的方法,如:

 

<body>

     username1: ${user.getUserName()}<br/>

     username2: ${user.setUserName("kkk")}<br/>

     username1: ${user.getUserName()}<br/>

</body>

显示:

username1: 张三
username2: 
username1: kkk

由于$user.setUserName("kkk ") 是void返回值方法,所以不会显示任何东西.

 

有大括号的是正规方式引用(取值),也可以使用简洁方式(去掉大括号),如:

$username

不过一些特殊场合必须加,如有一个vice变量

${vice}hello

如果不加就成了$vicehello,找不到变量了

取值的规则

$customer.address

查找顺序是:

1、getaddress()

2、getAddress()

3、get("address")

4、isAddress()

大写的属性名Address引用,将是:

1、getAddress()

2、getaddress()

3、get("Address")

4、isAddress()

默认显示空白

如果取值失败,默认会原样显示,如$user,如果user没定义,就会直接显示出来,可以加感叹号让他显示空白,如$!user或者$!{user}

 

set用法

set设置变量

set可以设置各种变量类型,如:

#set( $monkey = $bill ) ## 设置变量

#set( $monkey.Friend = "monica" ) ## 设置字符串

#set( $monkey.Blame = $whitehouse.Leak ) ## 设置变量的属性

#set( $monkey.Plan = $spindoctor.weave($web) ) ## 设置方法返回值

#set( $monkey.Number = 123 ) ##设置数字

#set( $monkey.Say = ["Not", $my, "fault"] ) ## 设置ArrayList

#set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"}) ## 设置Map

其中ArrayList用中括号,Map用大括号,跟json格式一样

ArrayList访问元素:

$monkey.Say.get(0)

Map访问元素

$monkey.Map.get("bannana")或者$monkey.Map.banana

注:set赋值时,如果赋值失败或者赋的是null值,都不会生效,如:

 

#set( $result = "kkk" )

$result

<br/>

#set( $result = $user.userName )

$result

此时如果user对象不存在或者user.userName是null,都不会赋值,都输出

kkk

kkk

 

注:set赋值变量时,如果右边是单引号,则不会取变量值,原样输出,如果是双引号,则会取出变量值,如:

1、单引号,原样输出:

#set($a = "kkk" )

        #set($b = "ggg")

        #set($c = '$a + $b')

$c

输出:

$a + $b

也可以通过配置来让他转义:

velocity.properties such that stringliterals.interpolate=false.

2、双引号,变量转义后输出

 

#set($a = "kkk" )

        #set($b = "ggg")

        #set($c = "$a + $b")

$c

输出

kkk + ggg

3、没有符号,做运算

 

#set($a = "kkk" )

        #set($b = "ggg")

        #set($c = $a + $b)

$c

输出:

kkkggg

set计算

类似于jstl,vtl也能做计算,如:

 

        #set($foo = 5)

        #set($bar = 6)

          

#set( $value = $foo + 1 )

     $value<br/>

     #set( $value = $bar - 1 )

     $value<br/>

     #set( $value = $foo * $bar )

     $value<br/>

     #set( $value = $foo / $bar )

     $value<br/>

输出:

如果是字符串,则直接拼接,如:

        #set($foo = "5")

        #set($bar = "6")

          

#set( $value = $foo + 1 )

     $value<br/>

     #set( $value = $bar - 1 )

     $value<br/>

     #set( $value = $foo * $bar )

     $value<br/>

     #set( $value = $foo / $bar )

     $value<br/>

输出:

这里字符串只有+运算,-*/都没有,所以失败了,value的值没变(set赋值失败,原值不变),只有第一次"5"+"1"成功了,所以输出4个51

注:单引号跟双引号一样,都是字符串拼接

原样输出用#liternal() ….#end,不解析vtl

如:

 

        #set($a=5)

        #literal()

${a}

         #end

输出${a}而不是5

if语句

如后台设置了:

        ctx.put("a", 1);

vm页面:

        #if($a == '1')

            true enough

        #elseif($a == '2')

            a is 2

        #else

            no way!

        #end

输出:true enough

另:

$a == '1'

$a == 1

$a == "1"

三个都一样。

如果if、else等关键字前或后紧跟了其他字符,则可以用大括号隔开,如:

#if($a == "1")

            true enough#{else}no way!

     #end

 

注意:判断条件中如果只有一个变量,则只有当该变量找不到或者为null或者为false时,才不成立,其他时候都成立,如:

1

        #set($a="abc")

        #if($a)

            yes

        #else

            no

        #end

输出:yes

 

2

        #set($a="abc")

        #if($a.b)

            yes

        #else

            no

        #end

输出:no

3

        #set($a=false)

        #if($a)

            yes

        #else

            no

        #end

输出:no

注意:vtl中的所有数据类型都是对象,没有java中的int等类型,==比较时,都是调用toString方法,int等类型会自动转成Integer的封装。

 

支持与或非等语法,如:

        #if($a && $b)

        #if(!($a || $b))

for循环语句

遍历list(array)

后台代码:

 

        List<User> users = new ArrayList<User>();

        User user1 = new User("zhangsan", 29);

        User user2 = new User("lisi", 99);

        users.add(user1);

        users.add(user2);

        

        ctx.put("users", users);

        

        return getTemplate("test.vm");

vm代码:

 

        #foreach($user in $users)

            index:$velocityCount

            username:$user.userName

            age:$user.age

            <br/>

        #end

输出:

index:1 username:zhangsan age:29 
index:2 username:lisi age:99 

 

其中$velocityCount可以取得当前序号(计数器).

遍历map

后台代码:

 

        Map<String, User> usersMap = new HashMap<String, User>();

        User user1 = new User("wangwu", 30);

        User user2 = new User("zhaoliu", 100);

 

        usersMap.put("user1", user1);

        usersMap.put("user2", user2);

        ctx.put("usersMap", usersMap);

        

        return getTemplate("test.vm");

vm代码:

 

        #foreach($user in $usersMap)

            index:$velocityCount

            username:$user.userName

            age:$user.age

            <br/>

        #end

或者

        #foreach($userKey in $usersMap.keySet())

            index:$velocityCount

            username:$usersMap.get($userKey).userName

            age:$usersMap.get($userKey).age

            <br/>

        #end

输出:

index:1 username:zhaoliu age:100 
index:2 username:wangwu age:30 

 

$velocityCount的名字、初始值也可以进行配置,如:

directive.foreach.counter.name = myVelocityCount

directive.foreach.counter.initial.value = 100

名字就改成了myVelocityCount,初始值为100

include和parse包含

类似于jsp的include包含,如:

        #include("a.vm")

        #include("b.txt")

        #parse("c.vm")

        #include( "one.gif","two.txt","three.htm" )

        #include( "greetings.txt", $seasonalstock )

include包含的文件不会被解析,原样显示。

parse包含的文件会解析。

是否解析跟包含文件扩展名无关,只跟include还是parse命令有关

 

include可以一次包含多个,也可用变量名指定文件名

parse只能包含一个。

#parse 的模板中还可以再包含#parse声明,默认的深度为10,这是由配置参数directive.parse.max.depth决定的

stop

stop之后的内容停止输出(不仅是不解析,而且是所有的文件内容都不输出),以便用于调试,如:

 

        #set($a = 6)

        $a

        #stop

        abc

        $a
输出:
6

 

宏调用macro

无参宏

类似于freemarker,可以定义宏,解析之前自动替换内容,再解析,如:

 

        #macro( d )

welcome!

        #end

        

        #d()

输出:

welcome!

这里用macro定义了名称为d的宏,然后用#d()调用宏。

注意:宏定义改了之后,需要重启服务才会生效(调试时需注意)

 

带参数宏

如例1:

        #macro(d $a $b)

            hello,$a,$b

        #end

        

        #d("zhangsan", "lisi")

输出:

hello,zhangsan,lisi

 

其中,$a和$b是参数

 

例2:

 

        #macro(d $color $userList)

            color is $color </br>

            #foreach($user in $userList)

                $user <br/>

            #end

        #end

        

        #d("black", ["zhangsan", "lisi", "wangwu"])

输出:

color is black 
zhangsan 
lisi 
wangwu 

 

这里传了一个String参数$color和一个Arraylist参数$userList

转义

引用的转义

有时需要输出$、#这些

$2.5输出:$2.5    不会有问题,因为变量不能以数字开头

 

斜杠表示转义:

#set( $email = "foo" )

$email

\$email

\\$email

\\\$email

输出:

foo

$email

\foo

\$email

\\$email相当于\\ + $email,转义的斜杠+变量值,所以是\foo

\\\$email相当于\\ + \$email,转义的斜杠+转义的变量,所以是\$email

 

如果$email没有定义,则原样输出:

$email

\$email

\\$email

\\$email

命令的转义

与引用转义类似,在#号前加斜杠即可,

 

例1:

\#include( "a.txt" )

此时不会引入a.txt而是在页面上直接输出#include( "a.txt" )

 

例2:

\\#include ( "a.txt" )

此时输出\加a.txt的内容。

 

例3:

        \#if( $a )

hello

\#end

输出:

例4:

        #set($a = true)

        \\#if( $a )

hello

\\#end

输出:

因为\\被转义成了\

 

例5:

        #set($a = true)

        \#if( $a )

hello

#end

编译报错,因为只有#end,而#if被转义了。

范围操作,如:[3..5]等

范围操作边界只能是整数,每次递增(递减)1.

实质是生成了一个数组,只能用于#foreach或者#set命令标签。

一般用于网页设计者设计table等表格时,没有足够的填充数据时使用。

 

例1:    

    #foreach($a in [3..-2])

            $a <br/>

        #end

输出:





-1 
-2

   

例2:    

    #foreach($a in [3..3])

            $a <br/>

        #end

输出:


例3:

 

        #set($arr = [3..5])

        #foreach($a in $arr)

            $a <br/>

        #end

输出:



这里把范围[3..5]赋值给了$arr(实质是生成了一个数组[3,4,5]),再循环遍历

posted @ 2021-01-27 19:13  吴克兢  阅读(3687)  评论(0编辑  收藏  举报