一婆翔、引言
展示層有三大典型技術(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丹壕。
- maven依賴
<!--模板渲染引擎之velocity-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>${velocity.version}</version>
</dependency>
- 測(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());
}
}
- 測(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} 來(lái)使用定義的變量铣口。推薦使用
name 和
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 初步整合
- 添加依賴
<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>
- 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>
- 編寫/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>
- 添加
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/
- 編寫
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>
- 編寫
webapp/vm/test/index.vm
<h2>hello world!${name}</h2>
- 編寫測(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"模板舀瓢。
- 編寫
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>
- 完善測(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";
}
}
- 測(cè)試
測(cè)試1:訪問(wèn)localhost:8080/velocity/index
測(cè)試2:訪問(wèn)localhost:8080/velocity/login
可以看到廷雅,成功實(shí)現(xiàn)了不同頁(yè)面引用和不引用公共模板的功能。