velocity模板加载,路径问题

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();
        }
    }
}

猜你喜欢

转载自panyongzheng.iteye.com/blog/1882559