Velocity入門

Velocity

一、什麼是Velocity?

官網:http://velocity.apache.orghtml

Velocity是一個基於Java的模板引擎。它容許任何人使用簡單而強大的模板語言來引用Java代碼中定義的對象。java

當Velocity用於Web開發時,Web設計人員能夠與Java程序員並行工做,以根據模型 - 視圖 - 控制器(MVC)模型開發Web站點,這意味着網頁設計人員能夠專一於建立一個看起來很好的站點,程序員能夠專一於編寫一流的代碼。Velocity將Java代碼與網頁分開,使網站在其生命週期內更加可維護,併爲Java Server Pages(JSP)或PHP提供了可行的替代方案。程序員

Velocity的功能遠遠超出了網絡的範圍; 例如,它能夠用於從模板生成SQL,PostScript和XML。它能夠用做生成源代碼和報告的獨立實用程序,也能夠用做其餘系統的集成組件。例如,Velocity爲各類Web框架提供模板服務,使他們可以根據真正的MVC模型,使視圖引擎促進Web應用程序的開發。web

 

二、Velocity提供的project

Velocity Engine——這是實現全部工做的實際模板引擎。(目前的版本是1.7)spring

Velocity Tools——項目包含使用Velocity引擎構建Web和非Web應用程序的工具和其餘有用的基礎設施。在此找到例如Struts集成的代碼或獨立的VelocityViewServlet。(目前的版本是2.0)數據庫

三、入門示例

      個人項目是用了Spring Boot的,開始想在Spring.io中直接添加Velocity的依賴,可是找不到依賴包,只能後面導入了。apache

      個人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>app

 

而後在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";就能夠了。

 

四、User-guide

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

這個是Velocity的官方用戶指南,裏面寫了不少Veloctiy的語法和使用規範,下面就來試試看吧~

一、註釋Comment

單行註釋以##開始;

多行註釋是 #*  *#;

VTL註釋塊, #**    *# ,主要是用來存儲類信息和做者版本信息。

 

二、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

 

三、Formal Reference Notation正式參考符號

示例: ${vice}

通常用簡寫的符號 $vice ,跟上面的意思是同樣的。可是因爲可能存在歧義,好比Jack is a $vicemaniac ,這個時候就須要用正式的參考符號來消除歧義。

      當引用與模板中的文本直接相鄰時,正式符號一般頗有用。

四、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」。

五、Strict Reference Mode嚴格參考符號

Velocity 1.6引入了經過將速度配置屬性「runtime.references.strict」設置爲true來激活的嚴格參考模式的概念。這種設置的通常目的是使Velocity在未定義或不明確的狀況下更嚴格地執行,相似於編程語言,這可能更適合於Velocity的某些用途。在這種未定義或不明確的狀況下,Velocity會拋出異常。

使用此設置,引用須要被明確地放置到上下文中或者用#set指令定義,不然Velocity將拋出異常。在值爲null的上下文中的引用不會產生異常。另外,若是嘗試調用引用中沒有定義指定方法或屬性的對象的方法或屬性,那麼Velocity將拋出異常。若是嘗試在null值上調用方法或屬性,這也是正確的。

六、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}

 

七、Directives指令

指令以#開頭。

引用容許模板設計者爲網站生成動態內容,而指令 - 易於使用的腳本元素,可用於創造性地操縱Java代碼的輸出 - 容許網頁設計師真正負責網站的外觀和內容現場。

7.一、Set

#set指令沒有#end語句,這個要特別注意。

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

 

7.1.一、Literals文本

當使用#set指令時,將會解析和呈現包含在雙引號字符中的字符串文字。可是,當字符串文字包含在單引號字符中時,將不會被解析。另外,Velocity提供 #[[don't parse me!]]# ,使[[]]中間的內容不被解析。

舉例:

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

輸出爲:www/index.vm

7.二、Conditionals條件語句

7.2.一、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.二、Relational and LogicalOperators 關係和邏輯運算符

Velocity的運算符有== ,&&,|| ,! ,跟Java差很少,可是略有不一樣的是,Java的==只能判斷對象是否相等,而Velocity是能夠直接比較數字、字符串、對象是否相等的,當對象不一樣時,會調用toString()方法來比較。

7.三、Loops循環

7.3.一、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.四、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.五、Parse解析

#parse腳本元素容許模板設計者導入包含VTL的本地文件。Velocity將解析VTL並渲染指定的模板。像#include指令同樣,# parse可使用變量而不是模板。#parse引用的任何模板必須包含在TEMPLATE_ROOT下。與#include指令不一樣,# parse只會使用一個參數。

#parse("hello.vm")

運行結果顯示:這裏就能夠將title填充。

7.六、Break

#break指令中止當前執行範圍的任何進一步渲染。「執行範圍」本質上是內容的任何指令(即#foreach,#parse,#evaluate,#define,#macro或#@ somebodymacro)或任何「根」範圍(即template.merge(...) Velocity.evaluate(...)或velocityEngine.evaluate(...))。與#stop不一樣,#break只會中止最內層,即時範圍,而不是所有。

7.七、Stop

中止模板的任何進一步的渲染和執行。

7.八、Evaluate 評估

#evaluate指令可用於動態評估VTL。這容許模板評估在渲染時建立的字符串。這樣的字符串可能用於國際化模板或從數據庫中包含模板的部分。

示例:

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

顯示的是abc而不是abc1.

相關文章
相關標籤/搜索