Java中使用velocity實(shí)現(xiàn)模板渲染

一婆翔、引言

展示層有三大典型技術(shù)拯杠,分別是JSP、freemaker和velocity啃奴。本文主要介紹velocity潭陪。

Velocity 主要使用場(chǎng)景如下:

  • Web 應(yīng)用:開(kāi)發(fā)者在不使用 JSP 的情況下,可以用 Velocity 讓 HTML 具有動(dòng)態(tài)內(nèi)容的特性最蕾。
  • 源代碼生成:Velocity 可以被用來(lái)生成 Java 代碼依溯、SQL 或者 PostScript。
  • 自動(dòng) Email:很多軟件的用戶注冊(cè)瘟则、密碼提醒或者報(bào)表都是使用 Velocity 來(lái)自動(dòng)生成的黎炉。
    轉(zhuǎn)換 xml。

二醋拧、入門

velocity是一個(gè)基于java的模板引擎慷嗜,與freemarker齊名,下面寫一個(gè)velocity的hello world的demo丹壕。

  1. maven依賴
<!--模板渲染引擎之velocity-->
<dependency>
 <groupId>org.apache.velocity</groupId>
 <artifactId>velocity</artifactId>
 <version>${velocity.version}</version>
</dependency>
  1. 測(cè)試servelt
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * ==Velocity之Hello Wordld入門程序==
 * <p>
 * 首先庆械,我們?cè)诖a中初始化了VelocityEngine這個(gè)模板引擎,對(duì)其設(shè)置參數(shù)進(jìn)行初始化菌赖,
 * 指定使用ClasspathResourceLoader來(lái)加載vm文件缭乘。然后我們就可以往VelocityContext這個(gè)Velocity
 * 容器中存放對(duì)象了,在vm文件中我們可以取出這些變量琉用,從而進(jìn)行模板輸出忿峻。
 */
public class VelocityTest {

    private static final String VM_PATH = "template/velocity/helloworld.vm";

    public static void main(String[] args) {
        // 初始化模板引擎
        VelocityEngine velocityEngine = new VelocityEngine();
        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        velocityEngine.init();

        // 獲取模板文件
        Template template = velocityEngine.getTemplate(VM_PATH);

        // 設(shè)置變量,velocityContext是一個(gè)類似map的結(jié)構(gòu)
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("name", "world");
        List<String> list = new ArrayList<String>();
        list.add("jack");
        list.add("kitty");
        velocityContext.put("list", list);

        // 輸出渲染后的結(jié)果
        StringWriter stringWriter = new StringWriter();
        template.merge(velocityContext, stringWriter);
        System.out.println(stringWriter.toString());
    }
}
  1. 測(cè)試結(jié)果
hello world
1: This is jack
2: This is kitty

二辕羽、語(yǔ)法

2.1 變量

和我們所熟知的其他編程語(yǔ)言一樣,Velocity 也可以在模板文件中有變量的概念垄惧。

變量定義

#set($name =“velocity”)

等號(hào)后面的字符串 Velocity 引擎將重新解析刁愿,例如出現(xiàn)以$開(kāi)始的字符串時(shí),將做變量的替換到逊。

 #set($hello =“hello $name”)

上面的這個(gè)等式將會(huì)給 $hello 賦值為“hello velocity”

變量的使用
在模板文件中使用name 或者{name} 來(lái)使用定義的變量铣口。推薦使用 {name} 這種格式滤钱,因?yàn)樵谀0逯型瑫r(shí)可能定義了類似name 和 names 的兩個(gè)變量,如果不選用大括號(hào)的話脑题,引擎就沒(méi)有辦法正確識(shí)別names 這個(gè)變量件缸。

#set($name =“ricky”)

Welcome $name to velocity.com

2.2 循環(huán)

在 Velocity 中循環(huán)語(yǔ)句的語(yǔ)法結(jié)構(gòu)如下:

#foreach($element in $list)
 This is $element
 $velocityCount
#end

Velocity 引擎會(huì)將 list 中的值循環(huán)賦給 element 變量,同時(shí)會(huì)創(chuàng)建一個(gè) $velocityCount 的變量作為計(jì)數(shù)叔遂,從 1 開(kāi)始他炊,每次循環(huán)都會(huì)加 1.

2.3 條件語(yǔ)句

條件語(yǔ)句的語(yǔ)法如下:

#if(condition)
#elseif(condition)
#else
#end

2.4 關(guān)系操作符

Velocity 引擎提供了 AND、OR 和 NOT 操作符已艰,分別對(duì)應(yīng)&&痊末、||和! 例如:

#if($foo && $bar)
#end

2.5 宏

Velocity 中的宏可以理解為函數(shù)定義。定義的語(yǔ)法如下:

#macro(macroName arg1 arg2 …)
#end

調(diào)用這個(gè)宏的語(yǔ)法是:

#macroName(arg1 arg2 …)

這里的參數(shù)之間使用空格隔開(kāi)哩掺,下面是定義和使用 Velocity 宏的例子:

#macro(sayHello $name)
hello $name
#end
#sayHello(“velocity”)

輸出的結(jié)果為 hello velocity

2.6 內(nèi)嵌和引用

#parse#include 指令的功能都是在外部引用文件凿叠,二者的區(qū)別是:

  • #parse會(huì)將引用的內(nèi)容當(dāng)成類似于源碼文件,會(huì)將內(nèi)容在引入的地方進(jìn)行解析
  • #include是將引入文件當(dāng)成資源文件嚼吞,會(huì)將引入內(nèi)容原封不動(dòng)地以文本輸出

下面分別看兩個(gè)例子:

案例1:

## foo.vm 文件:
#set($name =“velocity”)
## parse.vm文件:
#parse(“foo.vm”)

輸出結(jié)果為:

velocity

案例2:

## foo.vm 文件:
#set($name =“velocity”)
## include.vm:
#include(“foo.vm”)

輸出結(jié)果為:

#set($name =“velocity”)

三盒件、Spring整合velocity進(jìn)行頁(yè)面展示

3.1 初步整合

  1. 添加依賴
<dependency>
    <groupId>org.apache.velocity</groupId>
     <artifactId>velocity</artifactId><!-- velocity與velocity-tools缺一不可 -->
     <version>1.6.2</version>
</dependency>
<dependency>
     <groupId>org.apache.velocity</groupId>
     <artifactId>velocity-tools</artifactId>
     <version>2.0</version>
</dependency>
  1. web.xml
<!-- 2. spring mvc核心:分發(fā)servlet -->
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- spring mvc的配置文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMVC.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
  1. 編寫/resources/spring-mvc.xml
<!--InternalResourceViewResolver視圖配置-->
    <!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">-->
    <!--<property name="prefix" value="/WEB-INF/pages/"/>-->
    <!--<property name="suffix" value=".jsp"/>-->
    <!--</bean>-->

    <!--velocity模板配置-->
    <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath" value="WEB-INF/views/"/><!-- 這個(gè)好像沒(méi)效果,velocity.properties中的配置起作用 -->
        <property name="configLocation" value="classpath:velocity.properties"/>
        <property name="velocityProperties">
            <props>
                <prop key="input.encoding">UTF-8</prop>
                <prop key="output.encoding">UTF-8</prop>
            </props>
        </property>
    </bean>

    <!--VelocityViewResolver視圖配置-->
    <!--<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">-->
    <!--<property name="suffix" value=".vm"/>-->
    <!--<property name="prefix" value=""/>-->
    <!--<property name="contentType" value="text/html;charset=UTF-8"/>-->
    <!--</bean>-->

    <!--
    layout功能
    上面我們使用的是VelocityLayoutWithCommonToolsViewResolver這個(gè)對(duì)象做為springmvc的視圖解析器舱禽,這個(gè)對(duì)象是集成了layout功能和tool功能為一體的解析器炒刁。
    對(duì)于一個(gè)WEB應(yīng)用來(lái)說(shuō),頁(yè)面的基本結(jié)構(gòu)往往是固定的呢蔫,頁(yè)面中的很多部分切心,例如頁(yè)面統(tǒng)一的頭部、尾部和菜單片吊,我們一般是不太需要變化的绽昏,各個(gè)頁(yè)面基本一致,變化的往往是頁(yè)面的具體內(nèi)容部分俏脊,這樣全谤,布局(layout)功能的使用,就能大大減化前端頁(yè)面的復(fù)雜性了爷贫。這里簡(jiǎn)單介紹一下如何使用velocity框架來(lái)實(shí)現(xiàn)頁(yè)面的布局认然。
    我們知道,要在spring框架中配置velocity漫萄,一般需要配置兩個(gè)bean卷员,一個(gè)是velocityConfig, 別一個(gè)則是viewResolver。先來(lái)看velocityConfig的配置腾务,基本配置如下所示毕骡,這里和不使用布局的配置方式?jīng)]有任何差別。
    1. 一般情況下,當(dāng)我們不使用velocity的布局功能時(shí)未巫,我們一般會(huì)把viewResolver的class配置為:
    org.springframework.web.servlet.view.velocity.VelocityViewResolver窿撬,當(dāng)需要使用布局功能的時(shí)候,viewResolver的class需要配置為:
    org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver叙凡,顧名思義劈伴,從命名中我們就能看出來(lái)這個(gè)viewResolver是支持layout功能的。
    2. 不同的是握爷,這里多了一個(gè)layoutUrl的屬性配置:這個(gè)配置是設(shè)置你的layout文件的存在路徑跛璧,需要注意的是,這個(gè)路徑不是相對(duì)于webapp路徑來(lái)的饼拍,而是相對(duì)于velocityConfig配置中的resourceLoaderPath屬性配置的路徑(resourceLoaderPath的路徑是相對(duì)于webapp的路徑)赡模。
    普通的頁(yè)面實(shí)現(xiàn):比如我們要輸出一個(gè)帶帶固定頁(yè)頭和頁(yè)尾的頁(yè)面,內(nèi)容就是screen_content的值师抄,最后使用普通解析器頁(yè)面如下:
    -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
        <property name="suffix" value=".vm"/><!-- 后綴可以是任何東西漓柑,只要跟你的文件后綴名相同,控制器進(jìn)行視圖重定向就能找到這個(gè)文件 -->
        <property name="prefix" value=""/>
        <property name="contentType" value="text/html;charset=UTF-8"/>
        <property name="layoutUrl" value="layout/layout.vm"/>
    </bean>
  1. 添加resources/velocity.properties
## 設(shè)置模板文件加載器叨吮,webapp從應(yīng)用根目錄加載
resource.loader = webapp
webapp.resource.loader.class = org.apache.velocity.tools.view.WebappResourceLoader
## 模板路徑辆布,根目錄下的vm文件夾,比如訪問(wèn)http://localhost:8080/velocity/t.htm茶鉴,則選中的模板路徑是webapp/vm/t.htm锋玲,如果沒(méi)配置,默認(rèn)是模板路徑是webapp/t.htm
webapp.resource.loader.path = /vm
## 設(shè)置編碼涵叮,不設(shè)置會(huì)中文亂碼
input.encoding = UTF-8
output.encoding = UTF-8
tools.view.servlet.layout.default.template=default.vm
# 默認(rèn)的布局文件位置
tools.view.servlet.layout.directory=/WEB-INF/layout/ 
  1. 編寫webapp/vm/layout/layout.vm
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    </head>

    <body>
        <div>header</div>

        <div>
            $screen_content
        </div>

        <div>footer</div>
    </body>
</html>
  1. 編寫webapp/vm/test/index.vm
<h2>hello world!${name}</h2>
  1. 編寫測(cè)試Controller
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * velocity與Spring MVC集成作為展示頁(yè)面Demo
 */
@Controller
@RequestMapping(value = "/velocity")
public class MyVelocityTestController {

    /**
     * 模擬首頁(yè)
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/index")
    public String index(Model model) {
        String name = "tester";
        model.addAttribute("name", name);
        return "test/index";
    }

3.2 velocity選擇不同的模板

系統(tǒng)中的登錄頁(yè)面所使用的模板與其他普通頁(yè)面使用的模板不同惭蹂,或者是某些頁(yè)面需要引用不同的模板。
先按照上節(jié)velocity(4) 的步驟配置好割粮,通過(guò)以上配置后普通頁(yè)面velocity會(huì)自動(dòng)套用layout/default.vm模板盾碗。如果登錄頁(yè)面需套用自己獨(dú)特的模板則如下可以在登錄頁(yè)面中添加:#set($layout="login_layout.vm"),則登錄頁(yè)面將套用"login_layout.vm"模板舀瓢。

  1. 編寫webapp/vm/layout/empty.vm
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    </head>

    <body>
        $screen_content
    </body>
</html>

webapp/test/login.vm

#set($layout="layout/empty.vm")
<h2>This is the login page</h2>
  1. 完善測(cè)試controller
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * velocity與Spring MVC集成作為展示頁(yè)面Demo
 */
@Controller
@RequestMapping(value = "/velocity")
public class MyVelocityTestController {

    /**
     * 模擬首頁(yè)
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/index")
    public String index(Model model) {
        String name = "tester";
        model.addAttribute("name", name);
        return "test/index";
    }

    /**
     * 模擬使用不一樣模板的登錄頁(yè)
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/login")
    public String login(Model model) {
        return "test/login";
    }
}
  1. 測(cè)試
    測(cè)試1:訪問(wèn)localhost:8080/velocity/index
test1

測(cè)試2:訪問(wèn)localhost:8080/velocity/login

test2

可以看到廷雅,成功實(shí)現(xiàn)了不同頁(yè)面引用和不引用公共模板的功能。

四京髓、參考資料

  1. velocity文集
  2. Velocity 快速入門教程
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末航缀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子堰怨,更是在濱河造成了極大的恐慌芥玉,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件备图,死亡現(xiàn)場(chǎng)離奇詭異飞傀,居然都是意外死亡皇型,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門砸烦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人绞吁,你說(shuō)我怎么就攤上這事幢痘。” “怎么了家破?”我有些...
    開(kāi)封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵颜说,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我汰聋,道長(zhǎng)门粪,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任烹困,我火速辦了婚禮玄妈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘髓梅。我一直安慰自己拟蜻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布枯饿。 她就那樣靜靜地躺著酝锅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奢方。 梳的紋絲不亂的頭發(fā)上搔扁,一...
    開(kāi)封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音蟋字,去河邊找鬼稿蹲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛愉老,可吹牛的內(nèi)容都是我干的场绿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嫉入,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼焰盗!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起咒林,我...
    開(kāi)封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤熬拒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后垫竞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體澎粟,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蛀序,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了活烙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徐裸。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖啸盏,靈堂內(nèi)的尸體忽然破棺而出重贺,到底是詐尸還是另有隱情,我是刑警寧澤回懦,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布气笙,位于F島的核電站,受9級(jí)特大地震影響怯晕,放射性物質(zhì)發(fā)生泄漏潜圃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一舟茶、第九天 我趴在偏房一處隱蔽的房頂上張望谭期。 院中可真熱鬧,春花似錦稚晚、人聲如沸崇堵。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鸳劳。三九已至,卻和暖如春也搓,著一層夾襖步出監(jiān)牢的瞬間赏廓,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工傍妒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留幔摸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓颤练,卻偏偏與公主長(zhǎng)得像既忆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嗦玖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Velocity是一個(gè)基于Java的模板引擎患雇,通過(guò)特定的語(yǔ)法,Velocity可以獲取在java語(yǔ)言中定義的對(duì)象宇挫,...
    請(qǐng)叫我林小李閱讀 141,629評(píng)論 3 46
  • Beetl2.7.16中文文檔 Beetl作者:李家智 <xiandafu@126.com> 1. 什么是Beet...
    西漠閱讀 2,681評(píng)論 0 0
  • 4. Web集成 4.1. Web提供的全局變量 Web集成模塊向模板提供web標(biāo)準(zhǔn)的變量苛吱,做如下說(shuō)明 reque...
    西漠閱讀 4,499評(píng)論 0 0
  • 背景:系統(tǒng)中的登錄頁(yè)面所使用的模板與其他普通頁(yè)面使用的模板不同,或者是某些頁(yè)面需要引用不同的模板器瘪。先按照上節(jié)vel...
    176b46c2b527閱讀 297評(píng)論 0 1
  • 渴了翠储,你為我端來(lái)一杯水绘雁。餓了挚币,你會(huì)翻箱倒柜為我找東西吃搅荞。每次做好飯香璃,你都是第一個(gè)給我盛上漓概,讓我先吃≈福…… 漸漸地办龄,...
    秋水涓涓閱讀 247評(píng)論 3 2