Velocity入门

官网:http://velocity.apache.org

Velocity是一个基于Java的模板引擎。它允许任何人使用简单而强大的模板语言来引用Java代码中定义的对象。

当Velocity用于Web开发时,Web设计人员可以与Java程序员并行工作,以根据模型 - 视图 - 控制器(MVC)模型开发Web站点,这意味着网页设计人员可以专注于创建一个看起来很好的站点,程序员可以专注于编写一流的代码。Velocity将Java代码与网页分开,使网站在其生命周期内更加可维护,并为Java Server Pages(JSP)或PHP提供了可行的替代方案。

Velocity的功能远远超出了网络的范围; 例如,它可以用于从模板生成SQL,PostScript和XML。它可以用作生成源代码和报告的独立实用程序,也可以用作其他系统的集成组件。例如,Velocity为各种Web框架提供模板服务,使他们能够根据真正的MVC模型,使视图引擎促进Web应用程序的开发。

 

2、Velocity提供的project

Velocity Engine——这是实现所有工作的实际模板引擎。(目前的版本是1.7)

Velocity Tools——项目包含使用Velocity引擎构建Web和非Web应用程序的工具和其他有用的基础设施。在此找到例如Struts集成的代码或独立的VelocityViewServlet。(目前的版本是2.0)

3、入门示例

      我的项目是用了Spring Boot的,开始想在Spring.io中直接添加Velocity的依赖,但是找不到依赖包,只能后面导入了。

      我的porm.xml如下:

<?xml version="1.0"encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.LilyDianer</groupId>
   <artifactId>FastNews</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>FastNews</name>
   <description>Demo project for Spring Boot</description>

      <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
         <version>1.3.5.RELEASE</version>
         <relativePath/> <!-- lookup parent from repository -->
      </parent>

      <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <java.version>1.8</java.version>
      </properties>

      <dependencies>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
         </dependency>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-velocity</artifactId>
         </dependency>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
         </dependency>

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
         </dependency>
      </dependencies>

      <build>
         <plugins>
            <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
         </plugins>
      </build>
   </project>


然后在resource/templates下新建一个news.vm

<html>
<body>
<pre>
 Hello Lily Velocity
  </pre>
</body>
</html>

然后在src/main/java下新建一个controller包,在该包中新建一个IndexController类,添加Controller注解,写一个news函数:

@Controller
  public class IndexController {
    @RequestMapping(value= {"/vm"} )
    public String news(){
        return "news";
    }
}

然后运行Application,在127.0.0.1:8080中查看:

第一次报错:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu Jul 27 13:10:00 CST 2017

There was an unexpected error (type=Not Found, status=404).

No message available

看了控制台提示的错误:

2017-07-27 13:10:56.038 ERROR 8872 --- [nio-8080-exec-1] org.apache.velocity                      : ResourceManager : unable to find resource 'news.vm.vm' in any resource loader.

2017-07-27 13:10:56.065 ERROR 8872 --- [nio-8080-exec-1] org.apache.velocity                      : ResourceManager : unable to find resource 'error.vm' in any resource loader.

因为我开始写的是:

return "news.vm";

但是其实Velocity是会默认给返回值后面再加一个.vm,所以就报错了。

改成return "news";就可以了。

 

4、User-guide

官方文档:https://velocity.apache.org/engine/devel/user-guide.html

这个是Velocity的官方用户指南,里面写了很多Veloctiy的语法和使用规范,下面就来试试看吧~

1、注释Comment

单行注释以##开始;

多行注释是 #*  *#;

VTL注释块, #**    *# ,主要是用来存储类信息和作者版本信息。

 

2、References 引用

2.1 Variables变量

变量的简写符号由前导“$”字符,后跟VTL 标识符组成。VTL标识符必须以字母、数字和下划线组成,其他字符无效。

当VTL引用变量(如$ foo)时,变量可以从模板中的set指令或Java代码中获取其值。例如,如果Java变量$ foo在请求模板时具有值栏,则bar将替换网页上$ foo的所有实例。

举例:项目要显示用户名。

首先需要importorg.springframework.ui.Model;

news.vm文件:

<html>
<body>
<pre>
 Hello Lily Velocity
  
    ##这里是注解
    #*
    * 这里还是注解
    * *#
  
    username: $!{username}
  
  </pre>
</body>
</html>

 

IndexController.java:

@RequestMapping(value= {"/vm"} )
  public String news(Model model){
    model.addAttribute("username","Lily");
    return "news";
  }

 

2.2 Properties属性

属性具有独特的格式,$和.组成:

例子,$customer.Address。它可以有两个含义。这可以意味着,查看标识为客户的哈希表,并返回与地址相关联的值。但是$ customer.Address也可以指一个方法(参考方法的引用将在下一节讨论);$ customer.Address可以是一个写入$ customer.getAddress()的缩写方式。当您的页面被请求时,Velocity将确定这两种可能性中的哪一种是有意义的,然后返回适当的值。

项目的实例:首先需要在model包中写一个User类,属性有name和age,并且需要生成对应的setter和getter方法,和构造方法:

然后在Controller中写:

model.addAttribute("user",new User("Dianer",23));

然后在news.vm中写:

User:${user.name}
User:${user.age}

 

 

2.3 Methods方法

以$开头,用.和()来表示引用方法,方法中间还可以用 ””来填充参数。从Velocity 2.0开始,方法调用现在提供了所有Java基本内置类型之间的隐式转换:数字,布尔和字符串。

上面的User中的get和set方法,实践一下:

method:${user.getName()}
method2:${user.setName("50")}
method3:${user.getName()}

 

 

2.4 Property Lookup Rules 属性查找规则

属性通常引用父对象的方法,确定哪个方法对应所请求的属性,Velocity根据下列命名约定尝试不同的替代方法:

1.    getaddress()

2.    getAddress()

3.    get("address")

4.    isAddress()

2.5 Rendering 渲染

将每个引用(无论是变量,属性还是方法)生成的最终值在呈现为最终输出时都将转换为String对象。如果有一个代表$ foo的对象(例如Integer对象),那么Velocity将调用它的.toString()方法来将对象解析成一个String。

2.6 Index Notation 索引符号

      使用表单的符号$foo[0]可以用于访问对象的给定索引。此形式与在给定对象上调用get(Object)方法同义。

$foo[0]       ## $foo takes in an Integer look up
$foo[$i]      ## Using another reference as the index   
$foo["bar"]   ## Passing a string where $foo may be a Map

 

3、Formal Reference Notation正式参考符号

示例: ${vice}

一般用简写的符号 $vice ,跟上面的意思是一样的。但是由于可能存在歧义,比如Jack is a $vicemaniac ,这个时候就需要用正式的参考符号来消除歧义。

      当引用与模板中的文本直接相邻时,正式符号通常很有用。

4、Quiet Reference Notation安静参考符号

这是 ! 的区别:

例如:

<input type="text" name="email" value="$email"/>
   <input type="text" name="email" value="$!email"/>
   <input type="text" name="email" value="$!{email}"/>

 

只有第一个框中有 $email ,后面两个是没有的。后面两个框:当初始加载表单并且$ email仍然没有值时,将输出一个空字符串,而不是“$ email”。

5、Strict Reference Mode严格参考符号

Velocity 1.6引入了通过将速度配置属性“runtime.references.strict”设置为true来激活的严格参考模式的概念。这种设置的一般目的是使Velocity在未定义或不明确的情况下更严格地执行,类似于编程语言,这可能更适合于Velocity的某些用途。在这种未定义或不明确的情况下,Velocity会抛出异常。

使用此设置,引用需要被明确地放置到上下文中或者用#set指令定义,否则Velocity将抛出异常。在值为null的上下文中的引用不会产生异常。另外,如果尝试调用引用中没有定义指定方法或属性的对象的方法或属性,那么Velocity将抛出异常。如果尝试在null值上调用方法或属性,这也是正确的。

6、Case Substitution 案例替换

Velocity利用Java的内省和bean特性,将Context中的对象的引用名称以及objects方法解析。可以在模板中几乎任何地方嵌入和评估引用。

以SunMicrosystems定义的Bean规范为基础的Velocity是区分大小写的; 然而,其开发人员尽可能地努力捕捉和纠正用户错误。当方法getFoo()在模板中引用时$bar.foo,Velocity将首先尝试$getfoo。如果这样做失败,那么会尝试$getFoo。同样,当模板引用时$bar.Foo,Velocity会首先尝试$ getFoo(),然后尝试getfoo()。

注意:模板中对实例变量的引用未解决。只有引用JavaBean getter / setter方法的属性等同于解析(即$foo.Name解析为Foo类的getName()实例方法,而不是Foo的公共Name实例变量)。

相同的示例有

$foo.getBar()
## is the same as
$foo.Bar

$data.setUser("jon")
## is the same as
#set( $data.User = "jon" )

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

 

7、Directives指令

指令以#开头。

引用允许模板设计者为网站生成动态内容,而指令 - 易于使用的脚本元素,可用于创造性地操纵Java代码的输出 - 允许网页设计师真正负责网站的外观和内容现场。

7.1、Set

#set指令没有#end语句,这个要特别注意。

#set($user.age=18)
age:${user.getAge()}

 

7.1.1、Literals文本

当使用#set指令时,将会解析和呈现包含在双引号字符中的字符串文字。但是,当字符串文字包含在单引号字符中时,将不会被解析。另外,Velocity提供 #[[don't parse me!]]# ,使[[]]中间的内容不被解析。

举例:

#set( $directoryRoot = "www" )
#set( $templateName = "index.vm" )
#set( $template = "$directoryRoot/$templateName" )
$template

输出为:www/index.vm

7.2、Conditionals条件语句

7.2.1、If / ElseIf / Else

#if( $user )
    <strong>Velocity!</strong>
#end
 
#set($foo=10)
#if( $foo < 10 )
    **Go North**
#elseif( $foo == 10 )
    **Go East**
#elseif( $bar == 6 )
    **Go South**
#else
    **Go West**

Velocity会对if后的($foo)进行评估,确定是否为真:

$ foo是一个具有真实值的布尔值(true/ false)

$ foo的是一个字符串或一个集合,其不为空和不为空

$ foo是等于零的数字

$ foo是一个不为空的对象(字符串,数字或集合除外)

 

使用if elseif 的时候,Velocity引擎会在发现第一个为真的表达式时停止。

7.2.2、Relational and LogicalOperators 关系和逻辑运算符

Velocity的运算符有== ,&&,|| ,! ,跟Java差不多,但是略有不同的是,Java的==只能判断对象是否相等,而Velocity是可以直接比较数字、字符串、对象是否相等的,当对象不同时,会调用toString()方法来比较。

7.3、Loops循环

7.3.1、Foreach Loop

Velocity使用foreach循环。对象可以是Vector,HashMap或者是Array。

(1)当对象是Array时:

Controller:

List<String> colors = Arrays.asList(new String[]{"RED", "GREEN", "BLUE"});
model.addAttribute("colors", colors);

news.vm

#foreach ($color in $colors)
    Color $!{foreach.index}/$!{foreach.count}: $!{color}
#end

 

(2)当对象是map时:

Controller:

Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < 4; ++i) {
    map.put(String.valueOf(i), String.valueOf(i * i));
}
model.addAttribute("map", map);

news.vm:

#foreach($key in $map.keySet())
    Number $!{foreach.index}/$!{foreach.count}: $!{key} $map.get($key)
#end

7.4、Include 包含

#include脚本元素允许模板设计者导入本地文件,然后将其插入到其中的位置的#include指令定义。该文件的内容不会通过模板引擎呈现。

示例:在templates下新建一个hello.vm

Title <h>$!titleLily<h>

然后在news.vm中include进去:

#set($title = "FastNews")
Include: #include("hello.vm")<br>

运行的结果显示,这里的set并不会填充到hello.vm中。

7.5、Parse解析

#parse脚本元素允许模板设计者导入包含VTL的本地文件。Velocity将解析VTL并渲染指定的模板。像#include指令一样,# parse可以使用变量而不是模板。#parse引用的任何模板必须包含在TEMPLATE_ROOT下。与#include指令不同,# parse只会使用一个参数。

#parse("hello.vm")

运行结果显示:这里就可以将title填充。

7.6、Break

#break指令停止当前执行范围的任何进一步渲染。“执行范围”本质上是内容的任何指令(即#foreach,#parse,#evaluate,#define,#macro或#@ somebodymacro)或任何“根”范围(即template.merge(...) Velocity.evaluate(...)或velocityEngine.evaluate(...))。与#stop不同,#break只会停止最内层,即时范围,而不是全部。

7.7、Stop

停止模板的任何进一步的渲染和执行。

7.8、Evaluate 评估

#evaluate指令可用于动态评估VTL。这允许模板评估在渲染时创建的字符串。这样的字符串可能用于国际化模板或从数据库中包含模板的部分。

示例:

#set($source1 = "abc")
 #set($select = "1")
 #set($dynamicsource = "$source$select")
## $dynamicsource is now the string '$source1'
 #evaluate($dynamicsource)

显示的是abc而不是abc1.

附: 开发环境做以下配置,可避免修改VTL重启容器

file.resource.loader.path = templates
file.resource.loader.cache = false
velocimacro.library.autoreload = true

 

以下是velocity在实际应用中的用法以及各用法需要注意的地方:

判断一个字符串类型的变量是否为空串或null

  1. 可能报错的写法: $!userBaseInfoVO.phone != ''

  2. 当userBaseInfo对象为null或userBaseInfoVO.getPhone()返回null,就报错了

  3. 建议写法: $stringUtil.isNotBlank($!userBaseInfoVO.phone)

 

判断boolean值

  1. 可能报错的写法: #if($stringUtil.equals($resultCode,"true"))

  2. 当resultCode对象为boolean类型就报错了

  3. 建议写法:#if($resultCode)或者 $stringUtil.equals(“$!resultCode“, "true")


判断两个字符串是否相等

  1. 可能报错的写法: $!resultCode.toString() == "1000"

  2. 当resultCode对象为null就报错了

  3. 建议写法: $stringUtil.equals($!resultCode, "1000")


判断两个非字符串对象是否相等

  1. 可能报错的写法: $accountTransRes.result != $TransResultEnum.TXN_RESULT_SUCCESS

  2. 当accountTransRes为null或accountTransRes.getResult()返回null,就报错了;另一种情况是,当accountTransRes.getResult()返回的类型与TransResultEnum.TXN_RESULT_SUCCESS不一致,也会报错。

  3. 建议写法: {{!$objectUtil.equals($accountTransRes.result, $TransResultEnum.TXN_RESULT_SUCCESS)

  4. }}


输出一个值

  1. 可能报错的写法: $accountTransRes.transAmount

  2. 当accountTransRes为null或accountTransRes.getTransAmount()返回null,就报错了

  3. 建议写法:

  4. $! {accountTransRes.transAmount}


赋值

  1. 可能报错的写法:

  2. #set ($login_email = $!rundata.request.getParameter('login_email'))

  3. 当rundate.getRequest().getParameter('...')返回null,就报错了

  4. 建议写法:

  5. #set ($login_email = $stringUtil.defaultIfNull($!rundata.request.getParameter('login_email')))

  6. 可能报错的写法:

  7. #set ($tradeTransportType = $tradeDetail.tradeLogistics.transportType.intValue())

  8. 当tradeDetail为null或tradeDetail.getTradeLogistics()或tradeDetail.getTradeLogistics().getTransportType()为null,就报错了。

  9. 建议写法:

  10. #set ($tradeTransportType =

  11. $objectUtil.defaultIfNull($!tradeDetail.tradeLogistics.transportType.intValue(), 0))


Money类的比较

  1. 错误的写法:#if($amount != 0)

  2. 因为$amount是money类型,不直接和0做比较。

  3. 建议写法:#if($!amount&& (0 != $!amount.cent.intValue()))


pojo中boolean属性的读取

  1. 如果你有如下的一个javabean:

  2. public class MoneyReportModel {

  3. ……

  4. /**优惠是否为负数,由于调整价格可能为负数,所以必须加上这个 */

  5. private boolean isNegConcession;

  6. ……

  7. }

  8. 在页面上面你应该如何读取isNegConcession这个变量呢?

  9. 错误的写法:$moneyReportModel.isNegConcession

  10. 正确的写法: $moneyReportModel.isNegConcession()

  11. 如果boolean的名字不是以is开头,比如:

  12. private boolean freezeFlag;

  13. 在页面上用

  14. $moneyReportModel. freezeFlag或$moneyReportModel. isFreezeFlag()都可以获取该变量的值。

<strong>vm页面循环显示list的值</strong>
  1. <select name="status">

  2. <option value="">全部</option>

  3. #foreach($sysdict in $sdList)

  4. <option value="$sysdict.code">$sysdict.name</option>

  5. #end

  6. </select>

 

vm页面循环显示map的值:

  1. Map m = new HashMap();

  2. m.put("113", "test1");

  3. request.setAttribute("dds", m);// 后台

  4.  
  5. vm页面

  6. #foreach($info in $dds.entrySet())

  7. $info.key

  8. $info.value

  9. #end

本文引用地址:https://blog.csdn.net/u014282557/article/details/76193014

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值