zoukankan      html  css  js  c++  java
  • Velocity Tools及VelocityViewServlet源代码解析

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

        public void setMessage(String m)
        {
            message = m;
        }

        /** To test exception handling in templates. */
        public boolean whine() {
            throw new IllegalArgumentException();
        }

    }

    这个类实现了一个简单的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-app version="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>
    <data type="number">
        <key>version</key>
        <value>1.1</value>
    </data>
    <data type="boolean">
        <key>isSimple</key>
        <value>true</value>
    </data>
    <data type="string">
        <key>foo</key>
        <value>this is foo.</value>
    </data>
    <data type="string">
        <key>bar</key>
        <value>this is bar.</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.

    Here we use a custom tool: Hello from ToyTool!

    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
            // included in the Content-Type header.
            if (!DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding))
            {
                int index = defaultContentType.lastIndexOf("charset");
                if (index < 0)
                {
                    // the charset specifier is not yet present in header.
                    // append character encoding to default content-type
                    defaultContentType += "; charset=" + encoding;
                }
                else
                {
                    // The user may have configuration issues.
                    velocity.warn("VelocityViewServlet: Charset was already " +
                                  "specified in the Content-Type property. " +
                                  "Output encoding property will be ignored.");
                }
            }

            velocity.info("VelocityViewServlet: Default content-type is: " +
                          defaultContentType);
        }

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

       protected void initVelocity(ServletConfig config) throws ServletException
        {
            velocity = new VelocityEngine();    // 实例化一个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 log
    runtime.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

    */
                ExtendedProperties defaultProperties = loadDefaultProperties();
                velocity.setExtendedProperties(defaultProperties);
            }
            catch(Exception e)
            {
                log("VelocityViewServlet: Unable to read Velocity Servlet configuration file: ", e);
                throw new ServletException(e);
            }

            // velocity.properties文件是可以由用户自己根据需要配置的,如果用户自己重新设置了该文件,在这里解析
            try
            {
                ExtendedProperties p = loadConfiguration(config);
                velocity.setExtendedProperties(p);
            }
            catch(Exception e)
            {
                log("VelocityViewServlet: Unable to read Velocity configuration file: ", e);
                log("VelocityViewServlet: Using default Velocity configuration.");
            }

           // 当velocity.properties文件加载完成,初始化VeloccityEngine
            try
            {
                velocity.init();
            }
            catch(Exception e)
            {
                log("VelocityViewServlet: PANIC! unable to init()", e);
                throw new ServletException(e);
            }
        }

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

        protected void initToolbox(ServletConfig config) throws ServletException
        {
            // 获取在web.xml中设置的toolbox.xml
            String file = findInitParameter(config, TOOLBOX_KEY);
            if (file == null)
            {
                // ok, look in the default location
                file = DEFAULT_TOOLBOX_PATH;
                velocity.debug("VelocityViewServlet: No toolbox entry in configuration."
                               + " Looking for '" + DEFAULT_TOOLBOX_PATH + "'");
            }

            // 获取一个管理toolbox.xml的管理toolboxManager
            toolboxManager =
                ServletToolboxManager.getInstance(getServletContext(), file);
        }

    ToolboxManager是一个接口:

    package org.apache.velocity.tools.view;

    import java.util.Map;
    public interface ToolboxManager
    {
        void addTool(ToolInfo info);
        void addData(ToolInfo info);
        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.");
        }

    原文转自:http://chenpingtai2008.iteye.com/blog/752187

  • 相关阅读:
    初识Django-前后端不分离(一)
    虚拟环境的搭建
    python+request+Excel做接口自动化测试(二)
    使用postman+newman+python做接口自动化测试
    如何处理接口响应结果分析
    request使用的封装
    python中unittest的使用
    使用python的接口测试环境搭建及使用
    关于测试流程的指导心得
    Redis 学习
  • 原文地址:https://www.cnblogs.com/jston/p/2916993.html
Copyright © 2011-2022 走看看