初识 Velocity

        Velocity的能力远不止web站点开发这个领域,例如,它可以从模板(Template)产生SQL和PostScript、XML,

它也可以被作一个独立工具来产生源代码和报告,或者作为其他系统的集成组件使用。Velocity也可以为Turbine

Web开发架构提供模板服( Template Service )。Velocity+Turbine提供一个模板服务的方式允许一个web应用以一个

真正的MVC模型进行开发。

Velocity Template Language(VTL)

       VTL使用 References 来在Web Site内嵌套动态内容,一个变量就是References的一种类型

       VTL使用 Directives 来控制要显示的Java代码逻辑。

       下面是一个VTL Statement的例子,它可以被嵌套到HTML代码中:

       #set ( $a = “Velocity” );

        和所有的VTL Statement一样,这个Statement以#字符开始,当一个在线用户请求页面时,Velocity

Templating Engine将查询当前整个页面以便发现所有#字符,然后确定哪些是VTL Statement,哪些不需要VTL

作任何事情。

       和其他References一样以$字符开始,而值总是以双引号封闭。Velocity中仅有String可以被赋值给变量

       记住以下的规则:

           使用$字符开始的References用于得到什么;使用#字符开始的Directives用于做些什么。

           一旦某个变量被分配了一个值,那么你就可以在HTML文件的任何地方引用它。

           为使包含VTL Directives的Statement更具可读性,尽量在新行开始每个VTL Statement,尽管不是必须这么作。

注释 

    单行注释: 
           ## This is a single line comment. 
    多行注释: 
          #* 
               Thus begins a multi-line comment.

               Online visitors won’t see this text because the Velocity Templating Engine will ignore it. 
          *# 
    文档格式: 
          #** 
              This is a VTL comment block and may be used to store such information as the document author

              and versioning information
              @version 5 
              @author 
           *# 

References

        在VTL中有三种类型的References:变量(Variables)、属性(Properties)、方法(Methods)

        前面提到Velocity中仅有String可以被赋值给变量,如果有一个对象$foo是一个Integer对象,那么Velocity将调

它的toString()方法将这个对象转型为String类型,然后将其进行赋值。

       (一)变量  格式同Java

       (二)属性

                例如 $customer.Address:

             (1)查找Map对象customer中以address为Key的值;

             (2)也可以表示调用customer对象的getAddress()方法。

               当页面被请求时,Velocity将确定以上两种方式选用哪种,然后返回适当的值。

       (三)方法  是一个由$开始并跟随VTL标识符组成的References,一般还包括一个VTL方法体,如:

                  $person.setAttributes( [“Strange”, “Weird”, “Excited”] ) 

                  VTL属性可以作为VTL方法的缩写:

                        $customer.getAddress()与$customer.Address效果相同,不同点在于能否指定一个参数列表

                        $data.getUser(“jon”) 
                        ## is the same as 
                        $data.User(“jon”) 

                        $data.getRequest().getServerName() 
                        ## is the same as 
                        $data.Request.ServerName 
                        ## is the same as 
                        ${data.Request.ServerName}

                注意:VTL中不会将Reference解释为对象实例变量。例如:$foo.Name将被解释为Foo对象的getName()

方法,而不是Foo对象的Name实例变量。

References的正式格式 表达如下: 
        ${ mudSlinger }        变量 
        ${ customer.Address }    属性 
        ${ purchase.getTotal() }    方法

Quiet reference notation        

        VTL支持静态引用符$!,以避免呈现不存在的或者空的引用。

       例如:

       

             当页面表单被初始加载时,变量$email还没有值,这时需要能够显示一个空白文本来代替输出"$email"字符

串。此时使用静态引用符$!比较合适:

      

     ##正式格式:
   
     

             这样文本框的初始值就不会是email而是空值。

字面量

       货币字符$:

             在VTL中使用$2.5这样的货币标识能被正常识别,因为VTL中的Reference以一个大写或者小写的字母开始      

       转义(逃逸)字符"\":

             例如:#set( $email = “foo” ) 

                       $email   ——>  foo
                      \$email   ——>  $email
                     \\$email   ——>  \foo
                    \\\$email   ——>  \\$email

            注意:VTL中未被定义的变量将被认为是一个字符串(即转义前后都相同)。

Directives    

           前面提到,使用$字符开始的References用于得到什么;使用#字符开始的Directives用于做些什么。

           例如#字符后紧跟一个Directive:set 时,表达式使用括号封闭,其中将一个值赋值给变量。变量被列在左

边(LHS),而值被列在右边(RHS)。

           LHS 必须是一个变量或者属性Reference。

           RHS 可以是 References(变量、属性、方法)、String、Number、ArrayList、加减乘除算术表达式。

       ##ArrayList      

           #set ($monkey.Say = [“Not”, $my, “fault”])  

       ##取值方法:
           
           $monkey.Say.get(0) 

          注意:

                (1)RHS是一个 null 时,VTL的处理将比较特殊:它将指向一个已经存在的 Reference。

          #set ( $resut = $query.criteria(“name”)) 
  
          The result of the first query is $result 

          #set ( $resut = $query.criteria(“address”)) 
  
          The result of the second query is $result 

          ## 如果$query.criteria(“name”)返回一个“bill”,
 
          ##而$query.criteria(“address”)返回的是null,
 
          ##则显示的结果如下: 
     
              The result of the first query is bill
 
              The result of the second query is bill

                     由此延伸出的情况:

          #set( $criteria = ["name", "address"]) 
          
          #foreach( $criterion in $criteria ) 
           
            #set( $result = $query.criteria($criterion)) 
            #if($result) 
               Query was successful 
            #end
 
          #end

          ## 在循环时第二次循环结果为false时,
          ## 此时程序将不能智能的根据 $result 值决定查询是否成功。在 $result 被#set后
          ##(added to the context),它不能被设置回null(removed from the context)。
          ## 打印的结果将显示两次查询结果都成功,但是实际上有一个查询失败。

         
          解决方案:采用预先定义的方式 
 
          #set( $criteria = ["name", "address"]) 
          
          #foreach( $criterion in $criteria ) 
           
            #set( $result = false )

            #set( $result = $query.criteria($criterion)) 
            #if($result) 
               Query was successful 
            #end
 
          #end

                   (2)单引号与双引号

                          变量或字符串封闭在双引号内能被正常解析,封闭在单引号内时将不被正常解析:

               #set ($foo = “bar”) 
       
               $foo   # bar
    
               #set ($blar = ‘$foo’) 

               $blar  # $foo

                          本特性可以通过修改velocity.properties文件来改变上面的特性是否有效:

                                     设置 stringliterals.interpolate = false 即可

         #if/#elseif/#else条件语句`         

           #if ($foo) 
             Velocity! 
           #end

           在以下两种条件下成立:
            (1) $foo 是一个boolean型的变量,且它的值为true
            (2) $foo变量的值不为null

           #if( $foo < 10 ) 
              Go North  
           #elseif( $foo == 10 ) 
              Go East  
           #elseif( $foo == 6 ) 
              Go South  
           #else 
              Go West  
           #end

   由于 Velocity Context仅仅能够包含对象,所以此处的数字或boolean等基本类型数据皆通过内省机制转成对应的包装类对象,

此外与Java不同的是,用“==”来比较两个是否相等,并且要求等号两边的值类型相同。           

        AND、OR和NOT逻辑运算符

             AND ——> &&

             OR   ——> ||

             NOT ——> !

       Foreach循环

    
       #foreach ($product in $allProducts)         
  • $product
  •         #end     
  ## 每次循环$allProducts中的一个值都会赋给$product变量。$allProducts可以是一个Vector、Hashtable或者Array。 ## 分配给$product的值是一个Java对象,并且可以通过变量被引用。例如:如果$product是一个Java的Product类, ## 并且这个Product的名字可以通过调用他的getName()方法得到。 如果$allProducts是一个Hashtable:
      #foreach ($key in $allProducts.keySet()) 
  • Key: $key -> Value: $allProducts.get($key)
  • $velocityCount
  •   #end 
 

          其中$velocityCount代表循环次数,是Velocity默认的名字,可以通过修改velocity.properties文件来设置;

默认情况下,计数从“1”开始,可以在velocity.properties设置从“1”还是从“0”开始:

                            directive.foreach.counter.name = velocityCount
                            directive.foreach.counter.initial.value = 1

        #include
          1. 引入本地文件(不包含VTL);

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

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

          4. 引入多个文件,可以用逗号分隔,括号内可以是文件名,但是更多的时候是使用变量。

         #parse

          1. 引入本地文件(包含VTL);

          2. 引入的文件只能位于TEMPLATE_ROOT目录下 ;

          3. 文件内容经过template engine处理;

          4. 括号内只能引入单个文件;

          5. 可以通过修改velocity.properties文件parse_direcive.maxdepth的值来控制一个模板包含的最多#parse的个

              数( 默认值是10 )。

          6. 支持递归调用,将引入的本地文件解析并执行。

        #stop

            停止执行模板引擎并返回,应用于Debug。

        #macro

            定义一段可重用的VTL。

           #macro ( d ) 
                
           #end


       上述Velocimacro被定义为d,可以用如下方式调用它: #d()        

       被调用时,Velocity将用替换为#d()。 

          每个Velocimacro可以拥有任意数量的参数――甚至0个参数,虽然定义时参数可以随意设置,

       但是调用这个Velocimacro时必须指定正确的参数:

         #macro ( tablerows $color $somelist ) 
          #foreach ( $something in $somelist ) 
             $something 
          #end 
         #end

         #set ($greatlakes = [ “Superior”, “Michigan”, “Huron”, “Erie”, “Ontario” ]) 
         #set ( $color = “blue” ) 
          
            #tablerows( $color $greatlakes ) 
         
结果显示如下:                                  
Superior
Michigan
Huron
Erie
Ontario
   

            Velocimacros可以在Velocity模板内实现行内定义(inline),也就意味着和同一个Web Site内的其他Velocity

模板不可以共享此定义。

           而定义一个被所有模板共享的Velocimacro,则可以定义在一个Velocimacros模板库(模板库在

velocity.properties中定义):

           velocimacro.library=VM_global_library.vm

          ( 默认情况下velocity查找唯一的一个库可以通过配置这个属性来指定自己的模板库,多个模板库用逗号隔开)

           Velocimacro 参数

                可以是 References(变量、属性、方法)、String、Number、ArrayList、boolean值。

                注意:当References作为参数传递给Velocimacro时,是以名字的形式传递的。也意味着参数的值在每次

Velocimacro内执行时才会被产生。所以可以将一个方法调用作为参数 (实际传入的是方法名) 传递给Velocimacro,

而每次Velocimacro执行时该方法都会调用并产生不同的值,例如:

      #macro (callme $a) 
        $a $a $a 
      #end 
      #callme($foo.bar()) 

      执行的结果是:Reference $foo的bar()方法被执行三次。 
      如果不需要该特性可以通过以下方法: 
  
      #set ($myval = $foo.bar()) 
      #callme ($myval) 

   velocity.properties中 常用属性配置:


    #模板编码:  
    input.encoding=ISO-8859-1 //模板输入编码  
    output.encoding=ISO-8859-1 //模板输出编码  
      
    #foreach配置  
    directive.foreach.counter.name = velocityCount //计数器名称  
    directive.foreach.counter.initial.value = 1 //计数器初始值  
    directive.foreach.maxloops = -1 //最大循环次数,-1为默认不限制directive.foreach.iterator.name = velocityHasNex //迭代器名称  
      
    #set配置  
    directive.set.null.allowed = false //是否可设置空值  
      
    #include配置  
    directive.include.output.errormsg.start =  //错误信息提示结束字符串  
      
    #parse配置  
    directive.parse.max.depth = 10 //解析深度  
      
    模板加载器配置  
    resource.loader = file //模板加载器类型,默认为文件,可定义多个  
    file.resource.loader.description = Velocity File Resource Loader //加载器描述  
    file.resource.loader.class = Velocity.Runtime.Resource.Loader.FileResourceLoader //加载器类名称  
    file.resource.loader.path = . //模板路径  
    file.resource.loader.cache = false //是否启用模板缓存  
    file.resource.loader.modificationCheckInterval = 2 //检查模板更改时间间隔  
      
    宏配置  
    velocimacro.permissions.allow.inline = true //是否可以行内定义  
    velocimacro.permissions.allow.inline.to.replace.global = false //是否可以用行内定义代替全局定义  
    velocimacro.permissions.allow.inline.local.scope = false //行内定义是否只用于局部  
    velocimacro.context.localscope = false //宏上下文是否只用于局部 任何在Velocimacro内通过#set()对context的修改被认为是针对此velocimacro的本地设置,而不会永久的影响内容。  
    velocimacro.max.depth = 20 //解析深度  
    velocimacro.arguments.strict = false //宏参数是否启用严格模式
    velocimacro.library.autoreload=false  // 控制Velocimacro库是否自动加载。当设置为ture时,对于一个Velocimacro的调用将自动检查原始库是否发生了变化,如果变化将重新加载它。这个属性使得你可以不用重新启动servlet容器而达到重新加载的效果,使用的前提就是resource loader缓存是off状态(file.resource.loader.cache = false)。  
      
    资源管理器配置  
    resource.manager.class = Velocity.Runtime.Resource.ResourceManagerImpl //管理器类名称  
    resource.manager.cache.class = Velocity.Runtime.Resource.ResourceCacheImpl //缓存器类名称  
      
    解析器池配置  
    parser.pool.class = Velocity.Runtime.ParserPoolImpl //解析池类名称  
    parser.pool.size = 40 //初始大小  
      
    Evaluate配置  
    directive.evaluate.context.class = Velocity.VelocityContext //上下问类名称  
      
    可插入introspector配置  
    runtime.introspector.uberspect = Velocity.Util.Introspection.UberspectImpl //默认introspector类名称  

 

 

你可能感兴趣的:(Velocity)