《Velocity java开发指南》中文版(二)

Velocity最通常用在servlet中做为www服务. 有非常多的理由告诉你这项任务是最适合Velocity完成的,最重要的一个就是Velocity's可以分离视图(表现层和)代码层.在这里可以看到更多的理由this.
在servlet中使用Velocity是非常简单的. 你只需要extend 己有的 VelocityServlet class和一个必须实现的方法: handleRequest().
public Template handleRequest( HttpServletRequest, HttpServletResponse, Context )
这个方法直接传送HttpServletRequestHttpServletResponse objects,. 这个方法可以返回null值表示所有处理己经完成, 相对而言,指示velocity调用velocity requestCleanup()更为常用. 如下代码示例(在例程中有)
public class SampleServlet extends VelocityServlet
{
    public Template handleRequest( HttpServletRequest request,
                                   HttpServletResponse response,
                                   Context context )
    {
 
        String p1 = "Jakarta";
        String p2 = "Velocity";
 
        Vector vec = new Vector();
        vec.addElement( p1 );
        vec.addElement( p2 );
 
        context.put("list", vec );
 
        Template template = null;
 
        try
        {
            template = getTemplate("sample.vm");
        }
        catch( ResourceNotFoundException rnfe )
        {
         // couldn't find the template
        }
        catch( ParseErrorException pee )
        {
          // syntax error : problem parsing the template
        }
        catch( Exception e )
        {}
 
        return template;
    }
}
 
看起来好熟悉吧? 除过处理一些异常,基本的功能Velocity都己为你准备好了, 就连在应用程序中要你写的merge() 这一步,VelocityServlet自己也己处理,这就是基本的用法:取得context, 加入我们自己的对象最后返回模板 template.
默认的 Context是作为 handleRequest() 传入的. 可以使用以下常量直接访问 request和response对象,VelocityServlet.REQUEST (value = 'req') and VelocityServlet.RESPONSE (value = 'res') ,如下是java例程 :
public Template handleRequest( Context context )
{
    HttpServletRequest request = (HttpServletRequest) context.get( REQUEST );
    HttpServletResponse response = (HttpServletResponse) context.get( RESPONSE );
 
   ...
}
可以在模板中如下访问:
#set($name = $req.getParameter('name') )
 
一些更高级的用法,如VelocityServlet base class 可以在处理请求时重写更多的签名方法 :

Properties loadConfiguration( ServletConfig )
这可以重写常规的配置方法. 这常用在修改日志路径或运行时改写webapp root的绝对路径.
 
你可以创建自己的Context object. 这可以使用更高级的技术, 如数据链或预载数据和工具类. 默认的实理仅返回一个己内置request and response 对象的VelocityContext.你直以在模板中直接访问他们的命令。
 
void setContentType( HttpServletRequest,HttpServletResponse )
你可以自己定义contentType, 或提取client定义的. 默认的contentType类型在velocity.properties文件中配置, 一般来说,默认的"text/html" 类型是不够详细的.
 
void mergeTemplate( Template, Context, HttpServletResponse )
你可以生成输出流(output stream). VelocityServlet使用含有多种输出对象的池, 在特定情形下,重写这个命令是有用的.
 
这个调用一般在处理完后做资源的清理工作,如有需要,在这个命令的重写内容中加上你的代码.
 
在处理中,当错误发生时,这个方法会被调用. 默认的实现是将发送一个简单的HTML格式的错误内容到客户端. 你可以重写以定制错误处理.
更多的信息,请参考 API documentation.
 
 
发布基于Velocity的servlets 时,需要参数来配置 Velocity runtime. 在Tomcat上, 一个简单的方法是将velocity.properties文件放到你的webApp root目录下 (webapps/appname ) 然后在 WEB-INF/web.xml 文件中加上以下几行 :
<servlet>
  <servlet-name>MyServlet</servlet-name>
 <servlet-class>com.foo.bar.MyServlet</servlet-class>
 <init-param>
      <param-name>properties</param-name>
      <param-value>/velocity.properties</param-value>
 </init-param>
</servlet>
 
以上配置将确保MyServlet 可以被载入,Velocity也将会使velocity.properties来初始化.
注意: Velocity 在运行时使用的是单实例模式, 因此将 velocity-XX.jar放到YourWebAPP/WEB-INF/lib目录即可. 但当多个webApp要使用时,放入CLASSPATH 或Servlet容器的顶层 lib是最好的选择.
Velocity被设计为一个通用的功具包,它也常用于一般的应用程序中. 如这篇指南开始所讨论的那样, 另外,这里还有一些对一般应用程序来说很有用的工具类:
Velocity 提供一个 utility class ( org.apache.velocity.app.Velocity ). 这个类中提共一个初始化Velocity所必需的方法, 具体的细节可以到文档中查看.
Velocity runtime engine在运行时是单实便模式,它可以给 Velocity的用户通过同一个jvm提供日志,资源访问方法. 这个engine运行时仅初始化一次. 当然,你可以尝初对init()进行多次调用, 但只有第一次有效. The Velocity utility class 目前提供5个命令来配置运行时engine:
这5个配置方法是 :
  • setProperty( String key, Object o )
    这么简单,不用解释了吧.
  • Object getProperty( String key )
    嗯,也不说了
  • init()
    用默认的参数文件初始化
  • init( Properties p )
    用一个特定的java.util.Properties对象初始化.
  • init( String filename )
    用指定名字的参数文件初始化
注意:除非你指定了,否则初始时会使用默认参数. 仅当在调用init()时的配置会对系统生效。
通用的 initializing Velocity 一般步骤如下:
  1. 设置你指定的配置参数值在文件org/apache/velocity/runtime/defaults/velocity.properties中,或放入java.util.Properties, 在第一次调用init( filename )init( Properties ) .
  2. 单独设置每个配置参数通过调用 setProperty(),最后调用init(). 这适合一些一有自己的CMS系统(configuration management system )程序。
运行时一但初始化, 你就可以开始工作了.. 只需要考虑组装什么样的数据对象到你的输出模板上, Velocity utility class 可以帮你更容易做到这些.这里有一些命令摘要描述如下 :
  • evaluate( Context context, Writer out, String logTag, String instring )
    evaluate( Context context, Writer writer, String logTag, InputStream instream )
    这个命令用来修饰输入流,你可以将包含TVL的模板文件从内置的String对象、DB、或非文件系统的数据源输入,.
  • invokeVelocimacro( String vmName, String namespace, String params[], Context context, Writer writer )
    你可以直接访问Velocimacros. 也可以通过evaluate()命令来完成,这里你只需简单的传入VM文件名(模板文件), 创建一组VM参数放到Context,然后输出. 注意放入Context的参数必须是键-值对出现的.
  • mergeTemplate( String templateName, Context context, Writer writer )
    这个命令用来执行Velocity的模板合并和渲染功能. 它将应用context中的数据对象到指定文件名的模板中.将结果输出的指定的Writer. 当然,如果没有特别的需要,不建议这么做.
  • boolean templateExists( String name )
    检测当前配置的资源中,是否存在name的模板名.
这样,我们就更容易编写使用Velocity的java代码了. Here it is
import java.io.StringWriter;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.VelocityContext;
 
public class Example2
{
    public static void main( String args[] )
    {
        /* first, we init the runtime engine. Defaults are fine. */
 
        Velocity.init();
 
        /* lets make a Context and put data into it */
 
        VelocityContext context = new VelocityContext();
 
        context.put("name", "Velocity");
        context.put("project", "Jakarta");
 
        /* lets render a template */
 
        StringWriter w = new StringWriter();
 
        Velocity.mergeTemplate("testtemplate.vm", context, w );
        System.out.println(" template : " + w );
 
        /* lets make our own string to render */
 
        String s = "We are using $project $name to render this.";
        w = new StringWriter();
        Velocity.evaluate( context, w, "mystring", s );
        System.out.println(" string : " + w );
    }
}
运行如上程序,在运行程序的目录下将得到模板文件 testtemplate.vm (默认配置中模板文件的输出位置是当前目录):
 
template : Hi! This Velocity from the Jakarta project.
 
string : We are using Jakarta Velocity to render this.
 
where the template we used, testtemplate.vm, is
Hi! This $name from the $project project.
在这里,我们不得不使用 mergeTemplate() and evaluate() in our program. 这主要是为了示例. 在一般应用中,这是很少使用到的,但我们提供了根据具体需要自由使用的途径.
这有点不和我们这篇文张本意的“基础功能指南”这一意图, 但我想这是必须知道的. 首先, 你得到一个放置了数据对象的context对象, 不用的是使用了命令 mergeTemplate(), mergeTemplate() 所做的工作是合并模板, 在运行时调用低层功能(lower-level). 接下来,通过evaluate()方法使用一个String动态生成模板.
这是同样简单的使用Velocity engine的方式,这些可选功能也许可以帮你做一些重复的工作,比如生成模板的模板:)
There are three exceptions that Velocity will throw during the parse / merge cycle在解析/合并(parse/merge)模板周期中,Velocity或能出现三个Velocity异常.另外,还可能会有 IO problems, etc. Velocity自定义的异常可以在package org.apache.velocity.exception:
  1. ResourceNotFoundException
    当velocity的资源管理器无法找到系统请求的资源时出现.
  2. ParseErrorException
    当parse模板文件中的 VTL 语法出错时出现.
  3. MethodInvocationException
    Thrown when a method of object in the context thrown an exception during render time,当处理模板中,context中的对象的命令调用出错时.
当然,每一次出错时,相关的消息内容会保存到运行时的日志文件中,获取更多资料,请查看API文档。
在以上的一些例程中,使用默认的properties配置你的程序非常方便. 但你可以根据自己的需要,用自己的配置文件通过在Velocity中调用init(String yourFileName)命令传入你的配置文件名, 或创建一个保存了你的配置参数的 java.util.Properties对象,通过调用 init(Properties)命令来实现. 这其中后一个方式是很便捷的, 你可以直接将一个独立的参数文件通过load()调用,将其中的配置参数置入Properties对象中. 你还可以做得列好---你可以在运行时运态的从你的程序框架中加入参数. 这样,你应可以将Velocity的配置参数和你原来应用的配置在不做大的更改情况下共用。
当需要从一个指定的目录提取模板文件时(默认为当前目录),你可以这样做 :
import java.util.Properties;
 ...
 
public static void main( String args[] )
{
    /* first, we init the runtime engine. */
 
    Properties p = new Properties();
    p.setProperty("file.resource.loader.path", "/opt/templates");
    Velocity.init( p );
 
    /* lets make a Context and put data into it */
 
 ...
这样,Velocity在需要时,将自动到 /opt/templates 目录下查找模板文件,如果有问题可以查看velocity.log中所记录的出详细出错信息。它会帮你有效的消息错误.
 
Application Attributes (应用程序属性)是和VelocityEngine 的运行时实例(Runtimeinstance)相关联的,名-值对(name-value pairs)格式的参数,可用来存运RuntimeInstance时的信息.
设计这个功能的目标是Velocity程序需要与应用层或用户定制部分(如日志,资源,装载器等)通信.
The Application Attribute API is very simple. From the application layer,在 VelocityEngine 和 Velocity classes 中都有如下命令:
public void setApplicationAttribute( Object key, Object value );
这里的key与value的设置没有任何限制,可以在程序运行中设置,这是不同与Velocity的init()调用的.
内部程序可以通过接口 RuntimeServices 如下的命令来取得这些参数:
public Object getApplicationAttribute( Object key ):
9.EventCartridge and Event Handlers(事件分发和处理)
从Velocity1.1版本起,加入了良好的事件处理机制. 你可将自己的事件处理器类注册给事件分发器(EventCartridge) , 事件分发器实际上扮演着Velocity engine在运行时访问事件处理器(event handlers)的一个代理的角色。目前,有3种Velocity系统定义的事件可以被处理,它们都位与包org.apache.velocity.app.event 中.
org.apache.velocity.app.event.NullSetEventHandler
当模板中#set() 指令关联的是一个空值时, 这是很常见的一个问题. The NullSetEventHandler 事件处理器可以让你决定如何处理,其接口代码如下.
public interface NullSetEventHandler extends EventHandler
{
    public boolean shouldLogOnNullSet( String lhs, String rhs );
}
 
org.apache.velocity.app.event.ReferenceInsertionEventHandler
 
A ReferenceInsertionEventHandler 这个事件处理器可以让开发者在引用对象值如($foo)输出到模板之前截取修改.
public interface ReferenceInsertionEventHandler extends EventHandler
{
    public Object referenceInsert( String reference, Object value );
}
 
org.apache.velocity.app.event.MethodExceptionEventHandler
 
当用户数据对象中的某个命令出错时, 实现了 MethodExceptionEventHandler接口的事件处理器将被调用以获得具体的命令名字和Exception对象. 事件处理器也可以重组一个有效的对象返回(一般用于统一的异常处理), 或向它的父类throws一个new Exception, MethodInvocationException接口如下:
public interface MethodExceptionEventHandler extends EventHandler
{
    public Object methodException( Class claz, String method, Exception e )
         throws Exception;
}
可以直接使用一个事件分发器(EventCartridge),如下例程在org.apache.velocity.test.misc.Test中:
...
 
import org.apache.velocity.app.event.EventCartridge;
import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
import org.apache.velocity.app.event.MethodExceptionEventHandler;
import org.apache.velocity.app.event.NullSetEventHandler;
 
 ...
 
public class Test implements ReferenceInsertionEventHandler,
                             NullSetEventHandler,
                             MethodExceptionEventHandler
{
    public void myTest()
    {
        ....
 
        /*
         * now, it's assumed that Test implements the correct methods to
         * support the event handler interfaces. So to use them, first
         * make a new cartridge
         */
        EventCartridge ec = new EventCartridge();
 
        /*
         * then register this class as it contains the handlers
         */
        ec.addEventHandler(this);
 
        /*
         * and then finally let it attach itself to the context
         */
        ec.attachToContext( context );
 
        /*
         * now merge your template with the context as you normally
         * do
         */
 
        ....
    }
 
    /*
     * and now the implementations of the event handlers
     */
    public Object referenceInsert( String reference, Object value )
    {
        /* do something with it */
        return value;
    }
 
    public boolean shouldLogOnNullSet( String lhs, String rhs )
    {
        if ( /* whatever rule */ )
            return false;
 
        return true;
    }
 
    public Object methodException( Class claz, String method, Exception e )
         throws Exception
    {
        if ( /* whatever rule */ )
           return "I should have thrown";
 
        throw e;
    }
}
 
 
10.Velocity Configuration Keys and Values(配置参数名字和值说明)
Velocity's runtime configuration is controlled by a set of configuration keys listed below Velocity的运行时配置由一个key-value列表控制.
Velocity中有一些默认的值在以下位置可以找到:
 /src/java/org/apache/velocity/runtime/defaults/velocity.defaults,Velocity基础配置,它会确保Velocity总是有一个“正常的”配置以便运行.但它不一定是你想要的配置.
任何配置必须在 init()调用前发生才会在运行时替换掉默认的配置。这意味着你只需改变你需要的而不是所有的配置都要动.
这一节: Using Velocity In General Applications 有关于configuration API的进一步说明.
以下,是默认配置的说明:
runtime.log = velocity.log
用以指定Velocity运行时日志文件的路劲和日志文件名,如不是全限定的绝对路径,系统会认为想对于当前目录.
runtime.log.logsystem
这个参数没有默认值,它可指定一个实现了interface org.apache.velocity.runtime.log.LogSystem.的自定义日志处理对象给Velocity。这就方便将Velocity与你己有系统的日志机制统一起来.具体可见
Configuring the Log System 这一节.
runtime.log.logsystem.class = org.apache.velocity.runtime.log.AvalonLogSystem
上面这行,是一个示例来指定一个日志记录器.
runtime.log.error.stacktrace = false
runtime.log.warn.stacktrace = false
runtime.log.info.stacktrace = false
这些是错误消息跟踪的开关.将会生成大量、详细的日志内容输出.
runtime.log.invalid.references = true
当一个引用无效时,打开日志输出. 在生产系统运行中,这很有效,也是很有用的调试工具.
input.encoding = ISO-8859-1
输出模板的编码方式 (templates). 你可选择对你模板的编码方式,如UTF-8.GBK.
output.encoding = ISO-8859-1
VelocityServlet 对输出流(output streams)的编码方式.
directive.foreach.counter.name = velocityCount
在模板中使用#foreach() 指令时,这里设定的字符串名字将做为context key 代表循环中的计数器名,如以上设定,在模板中可以通过 $velocityCount来访问.
directive.foreach.counter.initial.value = 1
#foreach() 中计数器的起始值.
directive.include.output.errormsg.start =
directive.include.output.errormsg.end =
使用#include()时,定义内部流中开始和结束的错误消息标记,如果两者都设这屯,错误消息将被输出到流中'.但必须是两都定义.
directive.parse.maxdepth = 10
定义模板的解析深度,当在一个模板中用#parse()指示解析另外一个模板时,这个值可以防止解析时出现recursion解析.
resource.manager.logwhenfound = true
定义日志中的 'found' 务目开关.当打开时,如Resource Manager第一次发现某个资源时, the first time, the resource name and classname of the loader that found it will be noted in the runtime log.
resource.loader = <name> (default = File)
Multi-valued key. Will accept CSV for value. (可以有多个以.号分开的值),可以理解为指定资源文件的扩展名.
<name>.loader.description = Velocity File Resource Loader
描述资源装载器名字.
<name>.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
实现的资源装载器的类名. 默认的是文件装载器.
<name>.resource.loader.path = .
Multi-valued key. Will accept CSV for value. 资源位置的根目录. 当前配置会使用FileResourceLoader and JarResourceLoader 遍历目录下的所有文件以查找资源.
<name>.resource.loader.cache = false
控制装载器是否对文件进行缓存.默认不存是为了方便开发和调试. 在生产环境布署(production deployment)时可设为true以提高性能, 这里参数 modificationCheckInterval应设为一个有效值—以决定多久reload一次.
<name>.resource.loader.modificationCheckInterval = 2
当模把caching打开时,这个以秒为单位的值指示系统多久检测一次模板是否己修改以决定是否需要,如果设为 <= 0, Velocity将不做检测.
FileResourceLoader 的默认参数完整示例:
resource.loader = file
 
file.resource.loader.description = Velocity File Resource Loader
file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
file.resource.loader.path = .
file.resource.loader.cache = false
file.resource.loader.modificationCheckInterval = 2
 
velocimacro.library = VM_global_library.vm
Multi-valued key. Will accept CSV for value.当Velocity engine运行时,要被载入的含有宏代码库的文件名. 所有模板都可访问宏(Velocimacros ). 这个文件位置在相对于资源文件的根目录下.
velocimacro.permissions.allow.inline = true
Determines of the definition of new Velocimacros via the #macro() directive in templates is allowed,定义在模板中是否可用#macro()指令定义一个新的宏. 默认为true,意味所有模板都可定义new Velocimacros. 注意,这个设定,如模板中的有可能替换掉全局的宏定义.
velocimacro.permissions.allow.inline.to.replace.global = false
控制用户定义的宏是否可以可以替换Velocity的宏库.
velocimacro.permissions.allow.inline.local.scope = false
控制模板中的宏的专有命名空间.When true, 一个模板中的 #macro() directive 只能被定义它的模板访问. 这意味者所有的宏都不能共想了,当然也不会互想扰乱、替换了.
velocimacro.context.localscope = false控制Velocimacro 的引用访问(set/get)是涉及到Context范围还是仅在当前的Velocimacro中.
velocimacro.library.autoreload = false
控制宏库是否自动载入. 设为true时,源始的Velocimacro 将根据是否修改过而决定是否需要reLoad,可在调试时很方便,不需重启你的服务器,如用参数 file.resource.loader.cache = false的设置一样,主要是为方便开发调试用.
runtime.interpolate.string.literals = true
Controls interpolation mechanism of VTL String Literals. Note that a VTL StringLiteral is specifically a string using double quotes that is used in a #set() statement, a method call of a reference, a parameter to a VM, or as an argument to a VTL directive in general. See the VTL reference for further information.
parser.pool.size = 20
控制Velocity启动是需要创建并放到池中预备使用的模板解析器的个数----这只是预装. 默认的20个对一般用户来说足够了. 即使这个值小了,Velocity也会运行时根据系统需要动态增加(但增加的不会装入池中). 新增时会在日志中输出信息
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.开始入门 3 1.Getting Started 3 2.Dependencies 依赖资源 3 2.参考资源: 4 3.它是如何工作的? 4 1.基本使用模式 4 4.单实例还是多实例(To Singleton Or Not To Singleton...)? 6 1.Singleton Model 6 2.Separate Instance 6 5. The Context 7 1.The Basics 7 2.在模板中用#foreach指令支持迭代对象 8 3.Context Chaining 9 4.模板中的己创建对象 10 5.Context对象的其它用法 10 6.Using Velocity In Servlets 11 1.Servlet Programming 11 2.Deployment 13 7. Using Velocity In General Applications 13 1.The Velocity Helper Class 14 2.Exceptions 16 3.其它细节 16 8.Application Attributes 17 9.EventCartridge and Event Handlers(事件分发和处理) 17 1.Event Handlers 17 2.Using the EventCartridge使用事件分发器 18 10.Velocity Configuration Keys and Values(配置参数名字和值说明) 20 1.Runtime Log 20 2.字符集编码问题 21 3.#foreach() Directive 21 4.#include() and #parse() Directive 21 5.资源管理 21 6.Velocimacro(宏配置) 22 7.语义更改 23 8.运行时配置 23 11.Configuring the Log System(日志记录配置) 23 1.一般的可选日志功能: 23 2.Simple Example of a Custom Logger 25 12.Configuring Resource Loaders(资源装载器配置) 26 1.Resource Loaders 26 2.Configuration Examples 27 3.插入定制资源管理器和Cache实现 29 13.Template Encoding for Internationalization(字符编码和国际化) 29 14.Velocity and XML 30 15.FAQ (Frequently Asked Questions) 32 1.Why Can't I Access Class Members and Constants from VTL? 32 2.Where does Velocity look for Templates? 33 16.Summary 33 17.Appendix 1 : Deploying the Example Servlet 33

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值