学习Velocity Tools

Apache官方网站Velocity Tools自带的例子(位置:\velocity-tools-1.4-src\examples\simple)。

新建一个Web Project,名称为Velocity。

在src下面实现一个ToyTool类,如下所示:

public class ToyTool

{

    private String message = "Hello from ToyTool!";

public String getMessage()

{

returnmessage;

}

    public void setMessage(String m)

{

message=m;

    }

    /** To test exception handling in templates. */

publicbooleanwhine(){

thrownewIllegalArgumentException();

    }

}

这个类实现了一个简单的JavaBean,带setter和getter,操作的属性是message。

模板文件为index.vm,内容如下所示:

<html>

<body>

I'm a velocity template.

#if( $XHTML )

#set($br="<br/>")

#else

#set($br="<br>")

#end

$br$br

Here we use a custom tool: $toytool.message

$br$br

Here we get the date from the DateTool: $date.medium

</body>

</html>

在这个自带的例子中,并没有实际实现一个自己的Servlet,而是直接使用了org.apache.velocity.tools.view.servlet.VelocityViewServlet,该类位于\velocity-tools-1.4-src\src\java\org\apache\velocity\tools\view\servlet下面。

用到org.apache.velocity.tools.view.servlet.VelocityViewServlet,在该类中实现了对toolbox.xml的解析。可以在web.xml中对应的配置来了解到都配置了哪些项。

web.xml中配置如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<web-appversion="2.4"

xmlns="http://java.sun.com/xml/ns/j2ee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<servlet>

<servlet-name>velocity</servlet-name>

<servlet-class>

org.apache.velocity.tools.view.servlet.VelocityViewServlet

</servlet-class>

<init-param>

<param-name>org.apache.velocity.toolbox</param-name>

<param-value>/WEB-INF/toolbox.xml</param-value>

</init-param>

<load-on-startup>10</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>velocity</servlet-name>

<url-pattern>*.vm</url-pattern>

</servlet-mapping>

<welcome-file-list>

<welcome-file>index.vm</welcome-file>

</welcome-file-list>

</web-app>

其中,toolbox.xml的内容如下所示:

<toolbox>

<xhtml>true</xhtml>

<tool>

<key>toytool</key>

<class>ToyTool</class>

</tool>

<datatype="number">

<key>version</key>

<value>1.1</value>

</data>

<datatype="boolean">

<key>isSimple</key>

<value>true</value>

</data>

<datatype="string">

<key>foo</key>

<value>thisisfoo.</value>

</data>

<datatype="string">

<key>bar</key>

<value>thisisbar.</value>

</data>

<tool>

<key>map</key>

<class>java.util.HashMap</class>

</tool>

<tool>

<key>date</key>

<scope>application</scope>

<class>org.apache.velocity.tools.generic.DateTool</class>

</tool>

</toolbox>

将对应的jar包文件加入到CLASSPATH中,启动Tomcat Web Server ,在浏览器地址栏中键入http://localhost:8080/Velocity/index.vm就可以看到这个简单的例子运行的效果了:

I'm a velocity template.

Hereweuseacustomtool:HellofromToyTool!

Here we get the date from the DateTool: 2008-4-19 21:23:50

既然,web.xml中指定了初始化参数:key为org.apache.velocity.toolbox,value为/WEB-INF/toolbox.xml文件,那么,在Web Server(这里使用Tomcat)启动的时候,就要解析/WEB-INF/toolbox.xml。

其实,这里隐藏了很多细节,需要解析的不仅仅是/WEB-INF/toolbox.xml,在解析它之前还有很多工作要做。

可以在VelocityViewServlet的源代码中看到实际的过程。VelocityViewServlet继承了HttpServlet,表现出了它是有生命周期的。其中在init方法中可以看到初始化过程:

    public void init(ServletConfig config) throws ServletException

{

        super.init(config);

        // 根据config信息初始化Velocity,这时Web Server启动的时候要做的第一件事        initVelocity(config);

        // 初始化toolbox         initToolbox(config);

        // 当Velocity已经初始化完成之后,下面要做的一些事情:设置ContentType和编码等等等

defaultContentType=

            (String)getVelocityProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);

        String encoding =

(String)getVelocityProperty(RuntimeConstants.OUTPUT_ENCODING,

                                        DEFAULT_OUTPUT_ENCODING);

        // For non Latin-1 encodings, ensure that the charset is

//includedintheContent-Typeheader.

if(!DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding))

{

intindex=defaultContentType.lastIndexOf("charset");

if(index<0)

{

//thecharsetspecifierisnotyetpresentinheader.

//appendcharacterencodingtodefaultcontent-type

defaultContentType+=";charset="+encoding;

}

else

{

//Theusermayhaveconfigurationissues.

velocity.warn("VelocityViewServlet:Charsetwasalready"+

"specifiedintheContent-Typeproperty."+

"Outputencodingpropertywillbeignored.");

}

        }

        velocity.info("VelocityViewServlet: Default content-type is: " +

defaultContentType);

    }

上面代码中,第一件事是initVelocity,即窄initVelocity方法中注册Velocity引擎

   protected void initVelocity(ServletConfig config) throws ServletException

{

velocity=newVelocityEngine();//实例化一个VelocityEngine

        setVelocityEngine(velocity);    // 将已经创建的VelocityEngine设置到当前Velocity上下文中

        // 注册        LogSystemCommonsLog.setVelocityEngine(velocity);

        velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY, getServletContext());

        // 尝试读取VelocityTools 默认配置信息

try

        {

    /** 这里要读取Velocity的默认配置文件了,即org/apache/velocity/tools/view/servlet/velocity.properties文件,该文件默认设置如下所示:

# default to servletlogger, which logs to the servlet engines logruntime.log.logsystem.class = org.apache.velocity.tools.view.servlet.ServletLogger

# by default, load resources with webapp resource loader

resource.loader=webapp

webapp.resource.loader.class = org.apache.velocity.tools.view.servlet.WebappLoader

*/

ExtendedPropertiesdefaultProperties=loadDefaultProperties();

velocity.setExtendedProperties(defaultProperties);

}

catch(Exceptione)

{

log("VelocityViewServlet:UnabletoreadVelocityServletconfigurationfile:",e);

thrownewServletException(e);

        }

        // velocity.properties文件是可以由用户自己根据需要配置的,如果用户自己重新设置了该文件,在这里解析

try

{

ExtendedPropertiesp=loadConfiguration(config);

velocity.setExtendedProperties(p);

}

catch(Exceptione)

{

log("VelocityViewServlet:UnabletoreadVelocityconfigurationfile:",e);

log("VelocityViewServlet:UsingdefaultVelocityconfiguration.");

        }

       // 当velocity.properties文件加载完成,初始化VeloccityEngine

try

{

velocity.init();

}

catch(Exceptione)

{

log("VelocityViewServlet:PANIC!unabletoinit()",e);

thrownewServletException(e);

}

    }

接着就是initToolbox,开始解析/WEB-INF/toolbox.xml文件,initToolbox方法实现如下:

    protected void initToolbox(ServletConfig config) throws ServletException

{

//获取在web.xml中设置的toolbox.xml

Stringfile=findInitParameter(config,TOOLBOX_KEY);

if(file==null)

{

//ok,lookinthedefaultlocation

file=DEFAULT_TOOLBOX_PATH;

velocity.debug("VelocityViewServlet:Notoolboxentryinconfiguration."

+"Lookingfor'"+DEFAULT_TOOLBOX_PATH+"'");

        }

        // 获取一个管理toolbox.xml的管理toolboxManager

toolboxManager=

ServletToolboxManager.getInstance(getServletContext(),file);

    }

ToolboxManager是一个接口:

package org.apache.velocity.tools.view;

import java.util.Map;

publicinterfaceToolboxManager

{

voidaddTool(ToolInfoinfo);

voidaddData(ToolInfoinfo);

    Map getToolbox(Object initData);

}

它有一个实现子类XMLToolboxManager,可以完成对XML配置文件(比如toolbox.xml文件)的一些操作,其中,XMLToolboxManager类方法load实现了对XML文件的加载和解析:

    public void load(InputStream input) throws Exception

{

        LOG.trace("Loading toolbox...");

        Digester digester = new Digester();

digester.setValidating(false);

digester.setUseContextClassLoader(true);

digester.push(this);

digester.addRuleSet(getRuleSet());

        digester.parse(input);

        LOG.trace("Toolbox loaded.");

}

相关推荐