Getting Started with Velocity

Velocity

1. What is Velocity?

Official website: http://velocity.apache.org

Velocity is a Java-based template engine . It allows anyone to refer to objects defined in Java code using a simple and powerful templating language.

When Velocity is used for web development, web designers can work in parallel with Java programmers to develop web sites according to the Model-View-Controller (MVC) model, which means web designers can focus on creating a website that looks good site where programmers can focus on writing first-class code. Velocity separates Java code from web pages, making websites more maintainable over their lifetime and providing a viable alternative to Java Server Pages (JSP) or PHP.

Velocity's capabilities extend far beyond the web; for example, it can be used to generate SQL, PostScript, and XML from templates. It can be used as a standalone utility for generating source code and reports, or as an integrated component of other systems. For example, Velocity provides templating services for various web frameworks, enabling them to enable view engines to facilitate the development of web applications based on a true MVC model.

 

2. Project provided by Velocity

Velocity Engine - This is the actual template engine that does all the work. (current version is 1.7)

Velocity Tools - The project contains tools and other useful infrastructure for building web and non-web applications using the Velocity engine. Find here eg the code for the Struts integration or the standalone VelocityViewServlet. (current version is 2.0)

3. Getting started example

      My project uses Spring Boot, and I wanted to add Velocity's dependencies directly to Spring.io, but I couldn't find the dependency package, so I could only import it later.

      My porn.xml is as follows:

<?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>

 

Then create a new news.vm under resources/templates

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

Then create a new controller package under src/main/java, create a new IndexController class in the package, add the Controller annotation, and write a news function:

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

Then run Application and view it in 127.0.0.1:8080:

The first error:

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.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325938958&siteId=291194637