学习一个新技术 我们首先要了解 这个东西是什么?能做什么?怎么用?在更深层次了解就是 原理是什么? 我们就先来执行第一步 Velocity 是什么。访问velocity官网进行快速了解。http://velocity.apache.org/
大致内容如下:
Velocity是一个基于Java的模板引擎。它允许任何人使用简单但功能强大的模板语言来引用Java代码中定义的对象。
当Velocity用于Web开发时,Web设计人员可以与Java程序员并行工作,根据模型 - 视图 - 控制器(MVC)模型开发Web站点,这意味着Web页面设计人员可以专注于创建看起来不错的站点,程序员可以专注于编写顶级代码。Velocity将Java代码与网页分离,使网站在其生命周期内更易于维护,并提供Java Server Pages(JSP)或PHP的可行替代方案。
Velocity的功能远远超出了网络领域; 例如,它可用于从模板生成SQL,PostScript和XML。它既可以用作生成源代码和报告的独立实用程序,也可以用作其他系统的集成组件。例如,Velocity为各种Web框架提供模板服务,使它们能够通过视图引擎根据真正的MVC模型促进Web应用程序的开发。
接下来就是如何使用Velocity
我们可以查看寡官方的示例进行了解Velocity如何使用
http://velocity.apache.org/engine/1.7/developer-guide.html
http://velocity.apache.org/engine/1.7/user-guide.html
在使用之前我们先说明一下版本,我们公司目前使用的版本是 1.7 目前最新的版本是2.0 我们这里介绍的是1.7 版本。
开发工具:STS
JDK 1.8
在开始之前 我们先引入Velocity的插件。
好了闲话不多说,上代码:
第一步 引入Velocity的依赖
4.0.0
cn.lijunkui
velocitylearn
0.0.1-SNAPSHOT
war
org.apache.velocity
velocity
1.7
org.apache.velocity
velocity-tools
2.0
junit
junit
4.12
test
org.apache.maven.plugins
maven-surefire-plugin
true
maven-compiler-plugin
1.8
WebRoot\WEB-INF\web.xml
WebRoot
maven-war-plugin
3.0
false
velocitylearn
来一个hello word velocity
1 普通初始化
模板放在src目录下
package cn.lijunkui.api;
import java.io.PrintWriter;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
/**
* Velocity 使用demo 示例
* @author lijunkui
*
*/
public class VelocityDemo {
public void initVecocity() {
VelocityEngine ve=new VelocityEngine();
//设置模板加载路径,这里设置的是class下
ve.setProperty(Velocity.RESOURCE_LOADER, "class");
ve.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
try {
//进行初始化操作
ve.init();
//加载模板,设定模板编码
Template t=ve.getTemplate("cn/lijunkui/api/initVecocity.vm","gbk");
//设置初始化数据
VelocityContext context = new VelocityContext();
//设置输出
PrintWriter writer = new PrintWriter("D:\\helloword.html");
//将环境数据转化输出
t.merge(context, writer);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
编写vm的模板
Hello Velocity
Welcome use Velocity
编写测试用例:
package cn.lijunkui.api;
import org.junit.Before;
import org.junit.Test;
import cn.lijunkui.api.VelocityDemo;
public class VelocityDemoTest {
VelocityDemo demo = null;
@Before
public void before() {
demo = new VelocityDemo();
}
@Test
public void initVecocity() {
demo.initVecocity();
}
}
运行后会在 d盘生成一个名称为helloword.html 页面 如下图所示
2 采用properties方式进行初始化
编写vm的模板:
Hello Velocity
我的名字叫$name 年龄是$age;
public void initByProp() throws IOException {
Properties prop = new Properties();
// 配置模版目录
prop.put("file.resource.loader.path","D:\\workspace-sts-3.9.5.RELEASE\\velocitylearn\\src\\main\\resources\\template");
prop.put("input.encoding", "UTF-8");// 输入编码
prop.put("output.encoding", "UTF-8");//输出编码
Velocity.init(prop);
VelocityContext context = new VelocityContext();
StringBuffer str = new StringBuffer();
FileOutputStream outStream = null;
OutputStreamWriter writer = null;
File file = new File("D:/catalog");
if (!file.exists()) {
file.mkdirs();
}
Map map=new HashMap();
map.put("name", "张三");
map.put("age",34);
Set set = map.keySet();
Iterator it = set.iterator();
while(it.hasNext()){
String key = it.next();
context.put(key,map.get(key));
}
Template template = Velocity.getTemplate("hellovelocity.vm");
File destFile = new File("D:/catalog","studyCard.html");
outStream = new FileOutputStream(destFile);
writer = new OutputStreamWriter(outStream,"utf-8");
BufferedWriter sw = new BufferedWriter(writer);
template.merge(context, sw);
sw.flush();
sw.close();
writer.close();
outStream.close();
}
测试用例:
@Test
public void initByProp() throws IOException {
demo.initByProp();
}
单行注释 ## 内容
多行注释 #* 内容 *#
文档注释 #**内容*#
将我们后台操纵velocity引擎进行封装
private void test(String templatePath, String htmlPath) {
VelocityEngine ve=new VelocityEngine();
//设置模板加载路径,这里设置的是class下
ve.setProperty(Velocity.RESOURCE_LOADER, "class");
ve.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
try {
//进行初始化操作
ve.init();
//加载模板,设定模板编码
Template t=ve.getTemplate(templatePath,"utf-8");
//设置初始化数据
VelocityContext context = new VelocityContext();
//设置输出
PrintWriter writer = new PrintWriter(htmlPath);
//将环境数据转化输出
t.merge(context, writer);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void set() {
String templatePath = "cn/lijunkui/api/set.vm";
String htmlPath = "D:\\set.html";
test(templatePath,htmlPath);
}
@Test
public void set() {
demo.set();
}
模板内容如下:
#set($word="zhuoqianmingyue")
${word}#$word
#set($surname="Lee")
#set($name="junkui")
#set($fullname="$surname $name")
${fullname}
测试结果:
#if #elseif #else #end
模板内容:condition.vm
#set($number = 1)
#if($number == 1)
这个数是 1
#elseif($number == 2)
这个数是 2
#else
这个数是3
#end
/**
* 条件语句
*/
public void condition() {
String templatePath = "cn/lijunkui/api/condition.vm";
String htmlPath = "D:\\condition.html";
test(templatePath,htmlPath);
}
@Test
public void condition() {
demo.condition();
}
测试结果:
模板内容:
#foreach ( $item in [1..5] )
$item
#end
-------------------------------
#set ( $arr = [0..1] )
#foreach ( $x in $arr )
$x
#end
-------------------------------
#set ( $arr2 = [0..1] )
#set ( $k = 1 )
#foreach ( $x in $arr2 )
x:$x,k: $k
#set($k = $k+1)
#end
-------------------------------
public void foreach() {
String templatePath = "cn/lijunkui/api/foreach.vm";
String htmlPath = "D:\\foreach.html";
test(templatePath,htmlPath);
}
测试用例:
@Test
public void foreach() {
demo.foreach();
}
测试结果:
我个人理解为定义函数 这里要注意的是 宏不支持重载
#macro(html)
这是一个宏
#end
#macro(htmlContent $content)
$content
#end
#html()
#htmlContent("有参数的宏")
/**
* 定义宏标签
*/
public void macro() {
String templatePath = "cn/lijunkui/api/macro.vm";
String htmlPath = "D:\\macro.html";
test(templatePath,htmlPath);
}
@Test
public void macro() {
demo.macro();
}
测试结果:
停止执行模板引擎并返回,把它应用于debug是很有帮助的。
stop前的内容
#stop
stop后的内容
/**
* debug stop
*/
public void stop() {
String templatePath = "cn/lijunkui/api/stop.vm";
String htmlPath = "D:\\stop.html";
test(templatePath,htmlPath);
}
@Test
public void stop() {
demo.stop();
}
测试结果:
从测试结果中我们可以看出 stop 后面的内容并没有执行
4、"!"用来强制把不存在的变量显示为空白。
如当页面中包含$msg,如果msg对象有值,将显示msg的值,如果不存在msg对象同,则在页面中将显示$msg字符。这是我们不希望的,为了把不存 在的变量或变量值为null的对象显示为空白,则只需要在变量名前加一个“!”号即可。
模板内容:noexist.vm
#set($word="zhuoqianmingyue")
存在的内容:${word}#
不存在的内容:${word1}
不存在的内容不显示:$!{word1}
---------------------------
#if($!{word1})
存在
#else
不存在
#end
/**
* noexist
*/
public void noexist() {
String templatePath = "cn/lijunkui/api/noexist.vm";
String htmlPath = "D:\\noexist.html";
test(templatePath,htmlPath);
}
测试用例:
@Test
public void noexist() {
demo.noexist();
}
测试结果:
#include : 可以引入多个文件 而 #parse 只能引入单个文件
#include :被引入文件的内容将不会通过模板引擎解析 #parse 引入的文件内容Velocity将解析其中的velocity语法并移交给模板
#include( "abc.txt","cde.txt" )
public void include() {
String templatePath = "cn/lijunkui/api/include.vm";
String htmlPath = "D:\\include.html";
test(templatePath,htmlPath);
}
@Test
public void include() {
demo.include();
}
#parse 导入脚本
public void parse() {
String templatePath = "cn/lijunkui/api/parse.vm";
String htmlPath = "D:\\parse.html";
test(templatePath,htmlPath);
}
@Test
public void parse() {
demo.parse();
}
定义一个String工具类 将小写内容转换为大写
package cn.lijunkui.api;
public class StringUtils {
public static String toUpper(String word) {
return word.toUpperCase();
}
}
编写模板引擎初始化并将工具类的实例对象加载进模板的上下文中
public void initWihtFun(String templatePath, String htmlPath) {
VelocityEngine ve=new VelocityEngine();
//设置模板加载路径,这里设置的是class下
ve.setProperty(Velocity.RESOURCE_LOADER, "class");
ve.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
ve.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "D:\\workspace-sts-3.9.5.RELEASE\\velocitylearn\\target\\velocitylearn\\WEB-INF\\classes\\cn\\lijunkui\\api");
try {
//进行初始化操作
ve.init();
//加载模板,设定模板编码
Template t=ve.getTemplate(templatePath,"utf-8");
//设置初始化数据
VelocityContext context = new VelocityContext();
StringUtils stringUtils = new StringUtils();
context.put("stringUtils", stringUtils);
//设置输出
PrintWriter writer = new PrintWriter(htmlPath);
//将环境数据转化输出
t.merge(context, writer);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
编写模板内容:
useFun.vm
#set($word="zhuoqianmingyue")
$stringUtils.toUpper("abc")
$stringUtils.toUpper(${word})
编写测试用例:
public void useFun() {
String templatePath = "cn/lijunkui/api/useFun.vm";
String htmlPath = "D:\\useFun.html";
initWihtFun(templatePath,htmlPath);
}
@Test
public void useFun() {
demo.useFun();
}
测试结果
对数组的访问在Velocity中存在问题,因为Velocity只能访问对象的方法,而数组
又是一个特殊的Array,所以虽然数组可以进行循环列举,但却不能定位访问特定
位置的元素,如 strs[2],数组对固定位置元素的访问调用了Array的反射方法
get(Object array, int index),而Velocity没能提供这样的访问,所以数组要么改成
List等其他类容器的方式来包装,要么就通过公用Util类的方式来提供,传入数组
对象和要访问的位置参数,从而达到返回所需值的目的。