http://hi.baidu.com/ly_dayu/item/828b09c5c3c5e547a8ba9409
velocity使用基本来说比较简单,但在加载模板时老出问题,很多初学者经常会遇到找不到模板这种异常。本文就针对目前常用的三种模板加载方式做以说明。
一、velocity默认的加载方式(文件加载方式)
package com.velocity.test;
import java.io.StringWriter;
import java.util.Properties;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
/**
* 从文件中加载模板文件,即velocity默认的模板文件加载方式
* @author welcome
*
*/
public class LoaderFromFile {
public static void main(String[] args) throws Exception{
//初始化参数
Properties properties=new Properties();
//设置velocity资源加载方式为file
properties.setProperty("resource.loader", "file");
//设置velocity资源加载方式为file时的处理类
properties.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
//实例化一个VelocityEngine对象
VelocityEngine velocityEngine=new VelocityEngine(properties);
//实例化一个VelocityContext
VelocityContext context=new VelocityContext();
//向VelocityContext中放入键值
context.put("username", "张三");
context.put("password", "123456789");
context.put("age", "20");
context.put("address", "陕西西安");
context.put("blog", "http://blogjava.net/sxyx2008");
//实例化一个StringWriter
StringWriter writer=new StringWriter();
//从vm目录下加载hello.vm模板,在eclipse工程中该vm目录与src目录平级
velocityEngine.mergeTemplate("vm/hello.vm", "gbk", context, writer);
System.out.println(writer.toString());
}
}
二、从类路径加载模板文件
package com.velocity.test;
import java.io.StringWriter;
import java.util.Properties;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
/**
* 从class(类路径)中加载模板文件
* @author welcome
*
*/
public class LoaderFromClass {
public static void main(String[] args) throws Exception{
//初始化参数
Properties properties=new Properties();
//设置velocity资源加载方式为class
properties.setProperty("resource.loader", "class");
//设置velocity资源加载方式为file时的处理类
properties.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
//实例化一个VelocityEngine对象
VelocityEngine velocityEngine=new VelocityEngine(properties);
//实例化一个VelocityContext
VelocityContext context=new VelocityContext();
//向VelocityContext中放入键值
context.put("username", "张三");
context.put("password", "123456789");
context.put("age", "20");
context.put("address", "陕西西安");
context.put("blog", "http://blogjava.net/sxyx2008");
//实例化一个StringWriter
StringWriter writer=new StringWriter();
//从src目录下加载hello.vm模板
//假若在com.velocity.test包下有一个hello.vm文件,那么加载路径为com/velocity/test/hello.vm
velocityEngine.mergeTemplate("com/velocity/test/hello.vm", "gbk", context, writer);
//velocityEngine.mergeTemplate("hello.vm", "gbk", context, writer);
System.out.println(writer.toString());
}
}
三、从jar文件中加载模板文件
package com.velocity.test;
import java.io.StringWriter;
import java.util.Properties;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
/**
* 从jar文件中加载模板文件
* @author welcome
*
*/
public class LoaderFromJar {
public static void main(String[] args) throws Exception{
//初始化参数
Properties properties=new Properties();
//设置velocity资源加载方式为jar
properties.setProperty("resource.loader", "jar");
//设置velocity资源加载方式为file时的处理类
properties.setProperty("jar.resource.loader.class", "org.apache.velocity.runtime.resource.loader.JarResourceLoader");
//设置jar包所在的位置
properties.setProperty("jar.resource.loader.path", "jar:file:WebRoot/WEB-INF/lib/vm.jar");
//实例化一个VelocityEngine对象
VelocityEngine velocityEngine=new VelocityEngine(properties);
//实例化一个VelocityContext
VelocityContext context=new VelocityContext();
//向VelocityContext中放入键值
context.put("username", "张三");
context.put("password", "123456789");
context.put("age", "20");
context.put("address", "陕西西安");
context.put("blog", "http://blogjava.net/sxyx2008");
//实例化一个StringWriter
StringWriter writer=new StringWriter();
//从/WebRoot/WEB-INF/lib/vm.jar中加载hello.vm模板 vm.jar的目录结构为vm/hello.vm
velocityEngine.mergeTemplate("vm/hello.vm", "gbk", context, writer);
System.out.println(writer.toString());
}
}
velocity模板路径又一解
http://www.blogjava.net/patterns/archive/2006/11/28/velocity_template_path_another_method.html
研究hibernatesynchronizer的源码,看到他将velocity模板和编译的类一起打包在jar包中,在获得模板时使用
Xobject.class.getClassLoader().getResourceAsStream("/templates/xx.vm")
获得流,然后再将转变成字符串
public static String getStringFromStream(InputStream is) throws IOException {
if (null == is)
return null;
try {
InputStreamReader reader = new InputStreamReader(is);
char[] buffer = new char[1024];
StringWriter writer = new StringWriter();
int bytes_read;
while ((bytes_read = reader.read(buffer)) != -1) {
writer.write(buffer, 0, bytes_read);
}
return (writer.toString());
} finally {
if (null != is)
is.close();
}
}
最后调用velocity的方法
Velocity.evaluate(Context context, java.io.Writer out, java.lang.String logTag, java.lang.String instring)
从而生成文件。居然不知道velocity有这样的方法,挺无知的,为了路径焦头烂额,终于得解了。总结一下技巧:
1、
Xobject.class.getClassLoader().getResourceAsStream("/templates/xx.vm")相对路径获得流;
2、
Velocity.evaluate(...)方法使用;
velocity模板路径:
http://zhyt710.iteye.com/blog/235250
遇到的velocity加载模板时的路径问题。
于是查阅资料解决。最后综合velocity自己带的例子的example1和example2,改写了一个例子。怎样解决的在例子的注释中已经说的很明确。对于初学velocity的同志来说,这个例子可以是你参照学习的良好实例
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Properties;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
/**
* This class is a simple demonstration of how the Velocity Template Engine
* can be used in a standalone application using the Velocity utility class.
*
* It demonstrates two of the 'helper' methods found in the org.apache.velocity.util.Velocity
* class, mergeTemplate() and evaluate().
*
*
* @author <a href="mailto:[email protected]">Geir Magnusson Jr.</a>
* @version $Id: Example2.java 463298 2006-10-12 16:10:32Z henning $
*/
public class Example2
{
public static ArrayList getNames()
{
ArrayList list = new ArrayList();
list.add("ArrayList element 1");
list.add("ArrayList element 2");
list.add("ArrayList element 3");
list.add("ArrayList element 4");
return list;
}
public static void main( String args[] )
{
/* first, we init the runtime engine. Defaults are fine. */
Properties p = new Properties();
//设置输入输出编码类型。和这次说的解决的问题无关
p.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
p.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
//这里加载类路径里的模板而不是文件系统路径里的模板
p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
//也可以用下面方法指定一个绝对路径,不过这样要求你所有的模板都放在该路径下,是有局限的
//p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "模板路径");
try
{
Velocity.init(p);
}
catch(Exception e)
{
System.out.println("Problem initializing Velocity : " + e );
return;
}
/* lets make a Context and put data into it */
VelocityContext context = new VelocityContext();
context.put("name", "Velocity");
context.put("project", "阿帕奇");
context.put("list", getNames());
/* lets render a template */
StringWriter w = new StringWriter();
try
{
Velocity.mergeTemplate("example2.vm", "UTF-8", context, w );
}
catch (Exception e )
{
System.out.println("Problem merging template : " + e );
}
System.out.println(" template : " + w );
/*
* lets dynamically 'create' our template
* and use the evaluate() method to render it
*/
//这个例子也同时告诉我们可以先从文件系统读取一个文件到字符串,然后进行我们想要的操作
String s = "We are using $project $name to render this.";
w = new StringWriter();
try
{
Velocity.evaluate( context, w, "mystring", s );
}
catch( ParseErrorException pee )
{
/*
* thrown if something is wrong with the
* syntax of our template string
*/
System.out.println("ParseErrorException : " + pee );
}
catch( MethodInvocationException mee )
{
/*
* thrown if a method of a reference
* called by the template
* throws an exception. That won't happen here
* as we aren't calling any methods in this
* example, but we have to catch them anyway
*/
System.out.println("MethodInvocationException : " + mee );
}
catch( Exception e )
{
System.out.println("Exception : " + e );
}
System.out.println(" string : " + w );
///////////////////////////////////////////////////////
//其他方法: 1分别指定路径,此方法可以设定不同的路径 (也可是相对的。在eclipse下是工程目录)
try {
VelocityEngine velocityEngine = new VelocityEngine();
Properties properties = new Properties();
//也可以在这里指定绝对路径。当指定相对路径时, 在不同的环境下是有区别的。
//比如把程序部署到tomcat以后,相对路径相对到哪里是个很恶心的事情。
String basePath = "vm";
//可设置绝对路径
//String basePath = "F:/";
properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, basePath);
velocityEngine.init(properties);
Template template = velocityEngine.getTemplate("example2.vm");
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(System.out));
template.merge(context, writer);
writer.flush();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}