NVelocity用法



Velocity是一个基于Java的模板引擎。

NVelocity是一个基于.NET的模板引擎。

一、nVelocity的常用功能简介

    1、 在页面中定义变量,并进行简单的运算。

    2、 在页面中获得对后台程序实体对象的引用。

    3、 在页面中迭代实体对象集合。

    4、 在页面中获得实体对象的属性,及其方法。

    5、 对逻辑判断语句的支持。

    6、 对外部文件的引用。

    7、 对外部文件的解析。

二、nVelocity的工作原理

    可以使用.NET的反射实现。以下是nVelocity对迭代实体类的简单实现步骤:

    1、 定义People类,并拥有Name与Sex属性。表示一个人。

    2、 在页面中列出人物列表,则输入以下代码:

        #foreach($p in $ps)

          <p>欢迎您:$p.Name</p>

        #end

    3、 获取人物列表,保存在_List中。并指定页面中的字符串“ps”对应_List。

    4、以文本方式读取模板文件,并匹配#foreach…#end段,如果匹配到则继续匹配$X in $XX 段,分别记录用于保存集合与单项的字符,本次为“p”与“ps”。

    5 、用Type对象的GetProperties()方法获取_list中每一项的所有属性,并在#foreach  #end段中循环将$p + 属性名称替换为当前对象的当前属性的值。当然如果要调用对象的方法也可以用同样的方式获得。

三、基本语法

     1、特殊字符介绍

         A、“#”:表示开始做什么事情。

         B、“$”:表示用于获得什么。(以$开头的表示“引用”意思是取得一些东东.可引用变量,属性,方法)

         C、“##“:单行注释。

         D、 “#*… …*#”:多行注释。

     2、关键字

          A、 Set:开始做什么事情,比如定义变量,给变量重新赋值等。(注意:如果右边的操作数是一个属性或命令的引用而返回null,那么赋值将不会成功,且在随后的VTL中也不能再取出使用,如果要用做if条件,一个解决办法是,先给变量赋一个值,然后再将一个属性或命令的引用赋给该变量)

          B、 Foreach:迭代语句

          C、 If:条件判断语句

          D、 Elseif

          E、 Else

          F、 Include:对外部文件的引用,开始位置为模板路径。

          G、 Parse:对外部文件的引用,并用nVelocity方式解析。

          H、 Macro:创建宏,可以重复做某件事,类似于方法。

          I、  Even:双数执行

          J、  Odd :单数执行

          K、 Each:每次都执行

    (备注:所有变量在未定义之前不能使用(因为我们习惯了有全局变量的习惯),一个合法的VTL标示符是以一个字母开头的。.NET后台定义的对象除外。模板语言区分大小写,所有的关键字必须为小写,默认情况下,NVelocity解析是不分大小写的,当然可以通过设置runtime.strict.math=true,采用严格解析模式。)

四、使用示例

    1、  在页面中使用变量

        定义变量:#set($a = “CNF”)

        引用变量:欢迎光临:$a

         定义变量:#set($a = 1)

         运算:#set($a = $a + 1)

         输出:$a   ##得:2

         运算:#set($a = $a*5)

         输出:$a   ##得:10

       #set( $criteria = ["name", "address"] )

         #foreach( $criterion in $criteria )

               #set( $result = false )  //先设置默认值

               #set( $result = $query.criteria($criterion) )

               #if( $result )

                       Query was successful

              #end

         #end

     (备注:从以上可以看出nVelocity的替换顺序与.NET程序代码的执行基本一致,如果放在Foreach语句块中可以实现累加。并用If语句获得行号,对特殊行号的内容特殊处理。所有变量在未定义之前不能使用,.NET后台对象除外,最好采用正规引用格式,${a},正规引用格式一般用于在模板中直接调整字符串内容;静态引用输出:NVelocity遇到一个不能处理的引用时,一般他会直接输出这个引用$email的写法,页面上会看到的是$email,我们可以在$后面加上一个!号,那么就会输出空白.$!{email}如果不能处理会输出空白。如果email己定义了 (比如它的值是 foo),而这里你却想输出 $email. 这样一个字符串,就需要使用转义字符”\”,如:\$email)

    2、  在页面中使用条件判断语句

        #if ($p.StrSex == "女")

            #set($Sex = "女士")

       #elseif ($p.StrSex == "男")

            #set($Sex = "先生")

       #elseif ($p.StrSex == "无")

            #set($Sex = "人妖")

       #else

            #set($Sex = "怪物")

       #end

     (备注:可以嵌套在Foreach语句块中,用于对每个列表对象进行特殊显示处理。)

    3、  创建宏,可以当做方法使用。

         

创建:#macro(Add $a $b)

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

          <p>最后结果:$c</p>

      #end

 调用:#Add(1 2)

   

   (备注:模板引擎的初始化方法有3种,一种参数为模板文件内容,一种是带模板文件地址。结果发现带模板文件内容的,在应用宏的时候好像有点问题。另外一个就是假如在宏里面加入一个判断语句,则可以实现递归调用。)

    4、使用对象方法

        定义变量:#set($str = “CNF”)

        调用方法:$str.SubString(0,1) 

         输出:C

         定义变量:#set($a = 123)

         调用方法:$a.GetType()

         输出:System.Int32

    (备注:不管是.NET代码定义的对象,还是设计人员在页面中定义的变量,都可以使用对象的方法及属性,这一点非常强大。)

     5、使用even与odd简化代码,each辅助

         如上面所说用IF语句可以在列表中为每行创建不同的样式,但如果只需要区分单行与双行的话,可以使用even与odd简化代码。如下:

    

     #foreach($p in $ps)

              #even

              <p>双行:$p.StrName</p>

             #odd

             <p>单行:$p.StrName</p>

      #end

    (备注:在使用这两个关键字时,出现了与创建宏一样的问题,即在初始化模板引引擎的时候,如果是用模板文件内容初始化的,会出现问题)

     6、引用外部文件

          Include与parse都有引入外部文件的作用,不同的是parse会根据nVelocity模板语言解析外部文件。也就是说如果引入当前模板,则会出现死循环。

          #include 脚本元素让模板设计者可以在模板中引入一个本地文件, 这个被引入的文件将不会经过NVelocity的解析. 安全起见,可以引放的文件只是是配置参数TEMPLATE_ROOT所定义目录下的,默认为当前目录下.

#include( "head.html" )

        如果需要引入多个文件,可以像下面这样.   

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

            当然,还可用一个变量名来代替文件名引入.    

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

      #parse 元素指示可以引入一个包含TVL的本地文件,这个文件将被NVeloict engine解析输出。

#parse( "me.vm" )

         与 #include 指令不同, #parse 可以从引入的模板中得到变量引用.但#parse指令只能接受一个参数.VTL templates 被#parse 的模板中还可以再包含#parse声明,默认的深度为10,这是由配置参数directive.parse.max.depth在文件velocity.properties中决定的,你可以修改它以适合项目要求。

     7、使用Foreach语句

          上面多次列出Foreach语句,相信已经知道它的作用。即循环列出一组对象集合。比如:#foreach($p in $ps),其中$ps需要与后台代码中具体的实体类名称对应,$p代表$ps中的其中一项。上面已经提到过,即$p可以调用实体类的属性和方法。

    (备注:#foreach 语句必须以#end结束,通过引用变量$velocityCount可以访问到NVelocity提供的计数器:)

    8、创建数组

          创建:#set($List = [“男”,”女”])

          遍历:#foreach($Item in $List)

                      <p>List成员:$Item</p>

                       #end

          输出:List成员:男

               List成员:女

    VelocityHelper调用如下:

     

VelocityHelper vh = new VelocityHelper();

vh.Init("~/template/");    //模板路径

vh.Put("templateVariable", Variable);

vh.Display("index.htm");

附:NVelocity常用语法指令

    对变量的引用:$ [ ! ][ { ][ a..z, A..Z ][ a..z, A..Z, 0..9, -, _ ][ } ]。

       在NVelocity中,对变量的引用都是以$开头加上变量名称。当使用!时表示当此变量值为空时,显示空字符串。比如当$article为空,那会显示“$article“,而$!article会显示为“”。{}为变量名称限定,有时候变量名称后会有字符串,这是就需要用到{}了。比如$articleshow,想引用$article,这时只要修改为${article}就可以。其实,NVelocity对整个模板解析后都会变成这种模式。

     对属性的引用:$ [ { ][ a..z, A..Z ][ a..z, A..Z, 0..9, -, _ ]* .[a..z, A..Z ][ a..z, A-Z, 0..9, -, _ ]* [ } ] 。

     例如$article.Title或者${article.Title}。

     对方法的引用:$ [ { ][ a..z, A..Z ][ a..z, A..Z, 0..9, -, _ ]* .[ a..z, A..Z ][ a..z, A..Z, 0..9, -, _ ]*( [ optional parameter list...  ] ) [  } ]。

     例如:$article.GetListByTitle(‘nvelocity’)或${article.GetListByTitle(‘nvelocity’)}。其实对对象的属性值也可以用$article.get_Title()获得。

     赋值指令#set:# [ { ] set [ } ]  ( $ref = [ ", ' ]arg[ ", ' ] )。

     例如:$article.Title=’NVelocity’,$$article.Categories=[1,2,3],当然右侧也可以使用复杂的表达式:$article.Title=$otherArticle.Title.SubString(0,3),算术表达式:$article.Page=4/3等等。属性赋值也可以用$article.set_Title(‘NVelocity’)。

     条件指令#if:# [ { ] if [ } ] ( [condition] ) [output] [ # [ { ] elseif [ } ] ( [condition] ) [output] ]* [ # [ { ] else [ } ] [output] ] # [ { ] end [ } ] 。

     条件可以是返回bool的复查表达式。例如:#if($article.Total>1) $article.Title #else 没有数据 #end。

     循环指令#foreach:# [ { ] foreach [ } ] ($refinarg)statement# [ { ] end [ } ]。

     例如:#foreach($article in $articles) $article.Title #end。

     引用静态资源指令#include:# [ { ] include [ } ] ( arg[ arg2 ... argn] )。

      例如:#include(‘tmp.js’),会把tmp.js文件内容插入当前流。当然可以使用表达式:#include($article.Url)。

     引用并解析资源指令#parse:# [ { ] parse [ } ] ( arg )。

     例如:#parse(‘tmp.js’),与#include不同是,假如tmp.js文件中有NVelocity的指令,变量会进行处理,并把结果插入到当前流。

     停止指令#stop:# [ { ] stop [ } ] 。

     当NVelocity解析到此指令时,会停止解析过程。一般用户调试。

     计算指令#evaluate:# [ { ] evaluate [ } ] ( arg )。

     例如:#evaluate(‘$article.Title’),会在当前输出$article.Title

NVelocity的$与Jquery的$发生冲突时的解决方法有以下几个: 
1、 
使用jQuery.noConflict。 如:var j = jQuery.noConflict(); j.ajax(); 
缺点:当使用jQuery的相关插件时,会使得插件失效哦! 
2、 
使用jQuery代替$. 如:jQuery.ajax(); 
缺点:不适合扩展,一旦替换成第三方库时,那就麻烦大发 
3、 
wrap jQuery中的冲突方法。 
如$.ajax()在Velocity中会冲突,则重新定义如下: 
function dw(){} 
dw.ajax=function(s){ jQuery.ajax(s); } dw.ajax(); 
4、 
定义一个$JQ为$. 以后在js 中就可以用${JQ}AJAX了. 
在前台这样写(定义):#set($JQ="$.") 

==========================================================================================

==========================================================================================

==========================================================================================

Velocity是一个基于Java的模板引擎。

1. Velocity的介绍

Velocity是一个基于Java的模板引擎,其提供了一个Context容器,在java代码里面我们可以往容器中存值,然后在vm文件中使用特定的语法获取,这是velocity基本的用法,其与jsp、freemarker并称为三大视图展现技术,相对于jsp而言,velocity对前后端的分离更加彻底:在vm文件中不允许出现java代码,而jsp文件中却可以.

作为一个模块引擎,除了作为前后端分离的MVC展现层,Velocity还有一些其他用途,比如源代码生成、自动email和转换xml等,具体的用法可以参考这篇文章.

2. Velocty的基本用法

在这里我们以一个HelloVelocity作为Velocity的入门实例.首先在官网下载velocity的最新发布包,新建普通java项目,引入其中的velocity-1.7.jar和lib文件夹下的所有jar包即可. 然后分为如下两步:

2.1 初始化Velocity引擎

编写HelloVelocity.java文件如下:

public static void main(String[] args) {
    // 初始化模板引擎
    VelocityEngine ve = new VelocityEngine();
    ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
    ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
    ve.init();
    // 获取模板文件
    Template t = ve.getTemplate("hellovelocity.vm");
    // 设置变量
    VelocityContext ctx = new VelocityContext();
    ctx.put("name", "Velocity");
    List list = new ArrayList();
    list.add("1");
    list.add("2");
    ctx.put("list", list);
    // 输出
    StringWriter sw = new StringWriter();
    t.merge(ctx,sw);
    System.out.println(sw.toString());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

首先,我们在代码中初始化了VelocityEngine这个模板引擎,对其设置参数进行初始化,指定使用ClasspathResourceLoader来加载vm文件。然后我们就可以往VelocityContext这个Velocity容器中存放对象了,在vm文件中我们可以取出这些变量,从而进行模板输出.

2.2 编写hellovelocity.vm文件

其中,vm文件放在classpath目录下即可,类加载器会进行加载
hellovelocity.vm文件如下:

#set($greet = 'hello')
$greet $name 
#foreach($i in $list)
$i
#end
  • 1
  • 2
  • 3
  • 4
  • 5

控制台输出如下:

hello Velocity
1
2
  • 1
  • 2
  • 3

2.3 Velocity的基本语法

本文中只简单的介绍几个Velocity的基本语法,具体可以参考这篇文章

3.1 变量

在Velocity中也有变量的概念,使用$符声明变量,可以声明变量也可以对变量进行赋值(变量是弱类型的)。另外还可以使用$取出在VelocityContext容器中存放的值

#set(${!name} = "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])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

需要注意,上面代码中 $!{}的写法,使用$vari获取变量时,如果变量不存在,Velocity引擎会将其原样输出,通过使用\$!{}的形式可以将不存在的变量变成空白输出.

3.2 循环

在Velocity中可以使用循环语法遍历集合,语法结构如下:

#foreach($item in $list)
 $item
 $velocityCount 
#end
  • 1
  • 2
  • 3
  • 4

其中,$item代表遍历的每一项,velocityCount是Velocity提供的用来记录当前循环次数的计数器,默认从1开始计数,可以在velocity.properties文件中修改其初始值

3.3 条件控制语法

在Velocity中可以使用条件语法对流程进行控制

#if(condition)
...dosonmething...
#elseif(condition)
...dosomething...
#else
...dosomething...
#end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3.4 宏

在Velocity中也有宏的概念,可以将其作为函数来理解,使用#macro声明宏

## 声明宏
#macro(sayHello $name)
   hello $name
#end
## 使用宏
#sayHello("NICK")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.5 parse和include指令

在Velocity中可以通过parse或者include指令引入外部vm文件,但是二者存在区别:include指令会将外部文件原样输出,而parse指令会先对其进行解析再输出(即对外部文件中的vm语法解析)

#parse("header.vm")
#include("footer.vm")
  • 1
  • 2

4. 在web项目中使用Velocity

velocity只是一个模板引擎,在web项目中使用Velocity还得添加一个HTTP框架来处理请求和转发,apache提供了velocity-tools,其提供了VelocityViewServlet,也可继承VelocityViewServlet,从而实现自己的HTTP框架
一般都是继承VelocityViewServlet,重写handleRequest方法,在其中存入公共的参数.

通过继承或直接使用VelocityViewServlet,可以在管理的vm文件中获得request、session与application对象,也可以直接获取在这几个域对象中保存的值,获取的顺序与EL表达式获取的顺序类似:
${request} –> ${session} –> ${application}
比如${testArr}获取testArr属性,velocity会在velocity的context中寻找。没找到在request域中找,没找到在session中找.

下面将通过实例的方式讲解如何在web项目中使用Velocity
首先引入velocity-tools及其依赖的相关jar包,然后分为如下4步:

4.1 继承VelocityViewServlet

通过继承VelocityViewServlet重写handleRequest方法,可以自定义转发规则

public class MyVelocityViewServlet extends VelocityViewServlet {
    @Override
    protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) {
        // 往Context容器存放变量
        ctx.put("fullName","lixiaolin");
        // 也可以往request域中存值
        request.setAttribute("anotherName","xlli");
        // forward到指定模板
        return getTemplate("test.vm");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

4.2 配置web.xml

对自定义的VelocityViewServlet配置就像配置普通的Servlet一样,如下:

<servlet>
    <servlet-name>MyVelocityServlet</servlet-name>
    <servlet-class>com.lxl.velocity.MyVelocityViewServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyVelocityServlet</servlet-name>
    <url-pattern>/servlet/myVelocityServlet</url-pattern>
</servlet-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4.3 编写vm文件

vm文件是作为jsp的替代来展示给用户,在vm文件中可以获得在Context域或request等域中存放的值。默认情况下,会在资源根路径下搜索vm文件,所以直接将vm放在根路径下即可(也可以通过配置velocity.properties指定加载路径)
如下:

#set($greet = "hello")
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
 <p>$!{greet} $!{fullName}</p>
 <p>my another name is $!{anotherName}</p>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

4.4 配置velocity.properties

通过配置velocity.properties文件,可以自定义vm文件加载方式,指定编码等。当然,也可以不配置velocity.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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

最后,在浏览器中访问http://localhost:8080/VelocityApp/servlet/myVelocityServlet即可

5. 使用VelocityLayoutServlet

在web站点开发的过程中,经常会碰到几个页面的布局大致相同,比如引用相同的头部和尾部、左侧边栏相同等,在使用jsp开发时我们可以将头部等公共文件抽离出来,然后在实际页面中引入。Velocity也提供了类似的功能,并且该功能更加强大.

apache提供了VelocityLayoutServlet来实现页面布局,它是VelocityViewServlet的子类,通过使用VelocityLayoutServlet可以简化velocity下页面布局开发,可以使当forward到一个vm页面时,把该页面作为一个已有页面布局的一部分整体显示出来,比如访问资料页面,能够自动把头、尾部显示出来

velocity-tools包中已经包含了这个类,其使用分为如下几步:

5.1 配置velocity.properties

在/WEB-INF/路径下配置velocity.properties文件,指定模板布局文件的位置

input.encoding=UTF-8
output.encoding=UTF-8
## 定义加载器
resource.loader=webapp
webapp.resource.loader.cache=false
## 布局文件夹位置
tools.view.servlet.layout.directory = /templates/layout
## 定义默认布局文件
tools.view.servlet.layout.default.template = layout.vm
## 错误模板文件
tools.view.servlet.error.template = err.vm
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

5.2 布局母版vm文件

布局layout.vm文件是所有要展示的vm文件的母版,如下所示:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>${page_title}</title>
#if($!{CSS})
 #foreach($_css in ${CSS})
   <link type="text/css" rel="stylesheet" href="${ContextPath}/$_css">
 #end
#end
</head>
<body>
  <div class="header">
      #parse("/templates/layout/header.vm")
  </div>
  <div class="container">
      <div class="sub">
          #parse($sub)
      </div>
      <div class="main">
          $screen_content
      </div>
  </div>
#if($!JS)
 #foreach($_js in $JS)
   <script type="text/javascript" src="${CntextPath}/${_js}">
 #end
#end
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

其中,有个特殊的变量 screen_content,这是Velocity内置的变量,代表将要转发的页面

5.3 编写转发的vm文件

#set($layout = "/templates/layout/layout.vm")
#set($CSS = ["scripts/css/index.css"])
#set($JS = ["scripts/js/jquery-1.11.3.js"])
#set($page_title = "主页")
#set($sub = "/templates/sub.vm")

<div id="main-show">
    this is main-show
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

5.4 继承VelocityLayoutServlet

public class MyLayoutServlet extends VelocityLayoutServlet {
    @Override
    protected void doRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 设置通用的变量
        request.setAttribute("Request", request);
        request.setAttribute("ContextPath", request.getContextPath());
        request.setAttribute("BasePath", request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath());

        long runtime = System.currentTimeMillis();
        super.doRequest(request, response);

        if (request.getAttribute("close_comment") == null) {
            Date cur_time = Calendar.getInstance(request.getLocale()).getTime();
            PrintWriter pw = response.getWriter();
            pw.print("\r\n<!-- Generated by VelocityApp Server(");
            pw.print(cur_time);
            pw.print(") Cost ");
            pw.print(cur_time.getTime() - runtime);
            pw.print(" ms -->");
            pw.flush();
            pw.close();
        }
    }
}






  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值