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

11.Configuring the Log System(日志记录配置)
Velocity有很容易扩展的日志系统.即使不做任何设置,velocity也会将日志输出到当前目录下的 velocity.log文件中. 对一些高级用户, 可以很方便的将你当前系统的日志和它整合起来.
从1.3开始, Velocity 默认使用 Jakarta Avalon Logkit logger做为日志记录器,也可以用 Jakarta Log4j logger.首先它会在classpath中查找Logkit. 找不到,会再尝试Log4j.
  • Default Configuration
    默认在当前目录下创建日志文件.
  • Existing Log4j Category
    1.3开始, Velocity 可以将日志输出到Log4j配置中. 但你必须:
1.       确认 Log4j jar is in your classpath. ( 你应一直这样做,自从使用 Velocity.)
2.       配置 Velocit 使用 SimpleLog4JLogSystem class.
3.       通过 'runtime.log.logsystem.log4j.category' 参数指定日志条目名字 .
这里不建议使用老的 Log4JLogSystem class. 可以在随后看到示例 .
  • Custom Standalone Logger
    你可以创建定制的日志类你只需简单的实现接口org.apache.velocity.runtime.log.LogSystem然后将你的实现类名配置到运行时参数 runtime.log.logsystem.class的值, Velocityinit()时将创建你的日志实例. 更多相关信息可以看 Velocity helper class configuration keys and values. 要注意的是, 接口org.apache.velocity.runtime.log.LogSystem 1.2后才支持这一功能.
  • Integrated Logging
    你可以将Velocity的日志和你现存系统的日志整合到一起.
这里是一个使用 Log4j 做为 Velocity 日志的例子 .
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
 
import org.apache.log4j.Category;
import org.apache.log4j.BasicConfigurator;
 
public class Log4jCategoryExample
{
    public static String CATEGORY_NAME = "velexample";
 
    public static void main( String args[] )
        throws Exception
    {
        /*
         * configure log4j to log to console
         */
 
        BasicConfigurator.configure();
 
        Category log = Category.getInstance( CATEGORY_NAME );
 
        log.info("Hello from Log4jCategoryExample - ready to start velocity");
 
        /*
         * now create a new VelocityEngine instance, and
         * configure it to use the category
         */
 
        VelocityEngine ve = new VelocityEngine();
 
        ve.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
            "org.apache.velocity.runtime.log.SimpleLog4JLogSystem" );
 
        ve.setProperty("runtime.log.logsystem.log4j.category", CATEGORY_NAME);
 
        ve.init();
 
        log.info("this should follow the initialization output from velocity");
    }
}
上面的例子可以在examples/logger_example.下找到.
这是一个定制实现你自己的日志记录器,并将其加入到Velocity的日志系统中. LogSystem interface—只需要支持这个接口.
import org.apache.velocity.runtime.log.LogSystem;
import org.apache.velocity.runtime.RuntimeServices;
...
 
public class MyClass implements LogSystem
{
 
...
 
    public MyClass()
    {
        ...
 
        try
        {
            /*
             * register this class as a logger
             */
            Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, this );
            Velocity.init();
        }
        catch (Exception e)
        {
            /*
             * do something
             */
        }
    }
 
    /**
     * This init() will be invoked once by the LogManager
     * to give you current RuntimeServices intance
     */
    public void init( RuntimeServices rsvc )
    {
        // do nothing
    }
 
    /**
     * This is the method that you implement for Velocity to call
     * with log messages.
     */
    public void logVelocityMessage(int level, String message)
    {
        /* do something useful */
    }
...
}
 
12.Configuring Resource Loaders(资源装载器配置)
Velocity一个非常重要的基础功能是资源管理和装载. 这里资源 'resources' 不仅包括了模板('templates'),RMS也可以处理非模板文件, 特别是在使用 #include() 指令时.
resource loader system (资源装载系统)很容易扩展,可以同时执行多个资源装载器的操作. 这极大的方便了资源管理, --你可以根据需要,定制自己的资源装载器.
Velocity当前包含4种资源管理器, 说明如下:(注意例程中的配置参数有一个loader配置名 (ex.'file' in file.resource.loader.path).这个 'common name' 配置不一定会在你的系统中工作. 具体可见 resource configuration properties 理解系统如何工作. 这每一个loader都在包 org.apache.velocity.runtime.resource.loader. 中
  • FileResourceLoader : 这个loader从文件系统取得资源,其配置参数如下:
    • file.resource.loader.path = <path to root of templates>
    • file.resource.loader.cache = true/false
    • file.resource.loader.modificationCheckInterval = <seconds between checks>
这是己配置的默认装载器 , 默认从当前目录 ('current directory'). 但当你不想将模板入到 servlet 容器的启动目录下时,这个 loader 就无能为力了。请参看 developing servlets with Velocity.
  • JarResourceLoader : 这个loader可以从jar文件包中取得资源,在你把你的模板文件全部打包成 jar包时,系统会用这个loader来提取. 配置基本一样除过jar.resource.loader.path, 这里或以使用标准的JAR URL syntax of java.net.JarURLConnection.
  • ClasspathResourceLoader : classloader中取得资源. 一般来说,这意味着ClasspathResourceLoader将从classpathload templates.这是在Servlet类型应用常见的一种设置。支持Servlet 2.2 (或更新)规范的容器Tomcat就是这样一个例子. 这种装载方式很有效, 因此你必须将你的模板打成jar包放到你的web应用的WEB-INF/lib 目录下.就不再存在绝对、相对路径的问题了,与以上两个装载器相比 ClasspathResourceLoader不仅在servlet container中用也,几乎所有应用的上下文(context)都有用.
  • DataSourceResourceLoader : 这个loader可以从数据库载入资源. 这个loader不是标准j2EE的一部分,因此需要取得J2EE 发行库,j2ee.jar加入到build/lib目录下,然后编译新的Velocity.jar设置ant targetjar-j2ee,更细说明请见文档中对类 org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader的介绍.
己配置的loader,可以参看 resource configuration section, for further reference.
第一就是要配置 loader 的名字 . 参数 resource.loader 的值可以是你喜欢的用来关联指定 loader 的名字 .
resource.loader = file
下一步就是设置这个名字对应的class了,这是最重要的一步 :
file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
 
这个例子中,我们告诉 Velocity 我们设置的 loader 名字叫 file, 指定的类是 org.apache.velocity.runtime.resource.loader.FileResourceLoader. 下一步就是设置这个 loader 的一些重要参数 .
file.resource.loader.path = /opt/templates
file.resource.loader.cache = true
file.resource.loader.modificationCheckInterval = 2
 
这里,我们设置了查找模板的路径是 /opt/templates. 然后打开caching,最后,设置检测周期为2秒,以便Velocity检测新的或己更改过的模板来load.
上示是一些基本配置,随后,还会再有一些示例.
Do-nothing Default Configuration : 你也可以什么都不改动,就用默认的配置. 这是默认的loader配置:
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 = 0
 
Multiple Template Path Configuration :多模板路径配置如下所示,只要用逗号分开就是 :
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 = /opt/directory1, /opt/directory2
file.resource.loader.cache = true
file.resource.loader.modificationCheckInterval = 10
 
Multiple Loader Configuration : 多个loader配置,嗯,也很简单,不说了,看例子就是.
#
# specify three resource loaders to use
#
resource.loader = file, class, jar
 
#
# for the loader we call 'file', set the FileResourceLoader as the
# class to use, turn off caching, and use 3 directories for templates
#
file.resource.loader.description = Velocity File Resource Loader
file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
file.resource.loader.path = templatedirectory1, anotherdirectory, foo/bar
file.resource.loader.cache = false
file.resource.loader.modificationCheckInterval = 0
 
#
# for the loader we call 'class', use the ClasspathResourceLoader
#
class.resource.loader.description = Velocity Classpath Resource Loader
class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
 
#
# and finally, for the loader we call 'jar', use the JarResourceLoader
# and specify two jars to load from
#
jar.resource.loader.description = Velocity Jar Resource Loader
jar.resource.loader.class = org.apache.velocity.runtime.resource.loader.JarResourceLoader
jar.resource.loader.path = jar:file:/myjarplace/myjar.jar, jar:file:/myjarplace/myjar2.jar
 
只是注意: 'file', 'class', and 'jar' 这三个名字不是固定是,可以根据你的喜好来设定. 但只要保持上面的对应关系就是.
资源管理器是相关资源 (template and static content)管理系统的核心部分, 它为应用程序取得请求模板,查找他们的有效资源loaders,操作caching.对于高级用户,可以用自定制的caching系统取代这个默认的实现.
资源管理器必须实现 org.apache.velocity.runtime.resource.ResourceManager interface. 具体描述请看 api 文档 . 尽量使用默认实现,除非你认为有必要在以下参数中换成你自己的 :
resource.manager.class
 
这个参数也可通过RuntimeConstants.RESOURCE_MANAGER_CLASS 设定。
资源的 caching 必须实现 org.apache.velocity.runtime.resource.ResourceCache interface 接口 , 配置到参数中是 :
resource.manager.cache.class
这个参数也可通过 RuntimeConstants.RESOURCE_MANAGER_CACHE_CLASS 设定
 
从版本1.1开始, 可以设定资源的编解码类型. 在API中也可以传入解码的方式 :
org.apache.velocity.servlet.VelocityServlet :
public Template getTemplate( String template, String encoding )
org.apache.velocity.app.Velocity :
public static Template getTemplate(String name, String encoding)

public static boolean mergeTemplate( String templateName, String encoding, Context context, Writer writer )
encoding 参数可以设定为JVM支持的某个值 "UTF-8" or "ISO-8859-1".关于字符集正式的名字, see here.
注意,这仅仅是编码了模板自己 输出的编码由应用程序指定 .
 
 
Velocity's的VTL( velocity template language)处理XML数据很方便. Anakia 是一个用XSL从XML中输出视图的例子. Velocity站点,文档包括 Jakarta site is also rendered using Anakia.
一般来说,处理 XML 会用到 JDOM 这样的东东将 XML 转成 java 数据结构 , 如下例示是一个 XML 文档 :
<?xml version="1.0"?>
 
<document>
 <properties>
 <title>Developer's Guide</title>
 <author email="geirm@apache.org">Velocity Documentation Team</author>
 </properties>
</document>
 
一小段处理的读取XML的java程序如下:
...
 
SAXBuilder builder;
Document root = null;
 
try
{
    builder = new SAXBuilder( "org.apache.xerces.parsers.SAXParser" );
    root = builder.build("test.xml");
}
catch( Exception ee)
{}
 
VelocityContext vc = new VelocityContext();
vc.put("root", root );
 
...
 
(See the Anakia source for details on how to do this, or the Anakia example in the examples directory in the distribution.) 现在,在模板中应用 :
<html>
 <body>
    The document title is
    $root.getChild("document").getChild("properties").getChild("title").getText()
 </body>
</html>
 
就像渲染一般模板那样, 使用 Context 中的JDOM tree. 虽然这个例子看起来不漂亮, 但它展示了这样做是多么容易.
One real advantage of styling XML data in Velocity is that you have access to any other object or data that the application provides. You aren't limited to just using the data present in the XML document. You may add anything you want to the context to provide additional information for your output, or provide tools to help make working with the XML data easier. Bob McWhirter's Werken Xpath is one such useful tool - an example of how it is used in Anakia can be found in org.apache.velocity.anakia.XPathTool.
One issue that arises with XML and Velocity is how to deal with XML entities. One technique is to combine the use of Velocimacros when you need to render an entity into the output stream :
## first, define the Velocimacro somewhere
 
#macro( xenc $sometext )$tools.escapeEntities($sometext)#end
 
## and use it as
 
#set( $sometext = " < " )
<text>#xenc($sometext)</text>
where the escapeEntities() is a method that does the escaping for you. Another trick would be to create an encoding utility that takes the context as a constructor parameter and only implements a method:
public String get(String key)
{
    Object obj = context.get(key)
    return (obj != null) ? Escape.getText( obj.toString() ) : "";
}
 
Put it into the context as "xenc". Then you can use it as :
<text>$xenc.sometext</text>
 
This takes advantage of Velocity's introspection process - it will try to call get("sometext") on the $xenc object in the Context - then the xenc object can then get the value from the Context, encode it, and return it.
Alternatively, since Velocity makes it easy to implement custom Context objects, you could implement your own context which always applies the encoding to any string returned. Be careful to avoid rendering the output of method calls directly, as they could return objects or strings (which might need encoding). Place them first into the context with a #set() directive and the use that, for example :
#set( $sometext = $jdomElement.getText() )
<text>$sometext</text>
 
The previous suggestions for dealing with XML entities came from Christoph Reck, an active participant in the Velocity community. We are very grateful for his [unknowing] contribution to this document, and hope his ideas weren't mangled too badly :)
 
开发中常见的问题解答.
VTL 中无法访问到类的数据域
最简单的原因是我们无法反射/内省(introspect )这个对象.因为就OOP来说,对象中要隐藏自己没有必要外露的数据或命令.解决方法:包状成publicly 命令反回它,保证它是公开访问的. 当然,你要保证能改动源文件, 否则,就要用工具来解析它. org.apache.velocity.app.FieldMethodizer是用来解析你的类的, 如下示例如何将一个public static fields 导出到模板中.假设你的类是 :
public class Foo
    {
        public static String PATH_ROOT = "/foo/bar";
 
        ....
    }
 
 
你可这样将它放入context中:
context.put("myfoo", new FieldMethodizer( new Foo() ) );
 
然后在模板中就可以java代码的风格来访问 :
 $myfoo.PATH_ROOT
 
如果你需要访问public的非静态域时(public non-static members)甚止是私有成员!那你就必须扩展或重写 FieldMethodizer 这个类----但你为什么要搞得这么复杂呢?
Velocity 到哪里提取模板文件?
默认的,不做任何配置更改的情况下,Velocity会在当前目录下或相对与当前目录(如'foo/bar.vm')下查找.
Velocity对这些都是自动处理的. Velocity只记住它自己的一个root目录,这个概念不同与多根目录的文件系统(like - "C:\", "D:\", etc).
 
希望这个指南能帮助您出色的将 velocity 应用到项目中 . 请将您的意见反馈发送到 mail lists .
 
 
布署本文中的 Servlet 例程
Servlet开发者经常受到的一个打击是将servlet放错了地方---一切都是好的除此之外. 使用Tomcat 、 Resin i这样的Servlet容器都可以运行起我们的SampleServlet . SampleServlet.java 在目录 examples/servlet_example 下. 虽然有些servlet engines (Resin, for example) 会自动将它编译,但是为了学习,还是你亲自动手先将它编译过.
Jakarta Tomcat
Jakarta Tomcat 的安装就不多说了. 'webapp' 目录是tomcat默认的查找它的web应用的root.所以,以下是我们要做的:
  1. 首先,创建一个新的 'webapp' 暂时名叫 velexample 放到Tomcatwebapps 目录下, 这个新的目录结构如下 :
velexample
velexample/WEB-INF
velexample/WEB-INF/lib
velexample/WEB-INF/classes
  1. Velocity jar 放到velexample/WEB-INF/lib. (1.2版本后,所有相关依赖包都打包在. velocity-dep-1.2.jar),当然,相关的依赖包也必须放到WEB-INF/lib. 具体可以看 "Getting Started" and "Dependencies", 这两节的介绍.
  2. 将编译过的SampleServlet.class放到 velexample/WEB-INF/classes .
  3. sample.vm 放到目录velexample .
  4. 现在就可以启动servlet来访问servlet.
  5. Browser中输出如下 :
http://localhost:8080/velexample/servlet/SampleServlet
如不能工作,则试下 :
http://<your computer's ip address>:8080/velexample/servlet/SampleServlet
  1. 看到输出结果了吗?.
Setting up the example servlet under Caucho Technology's Resin servlet engine is also very simple. The following instructions were tested with the version 1.2.5 release. The following assume that you have unzip-ed or untar-ed the distribution, know how to start the servlet engine (something like bin/httpd.sh under unix...), and know where the doc directory is (in the root of the distribution).
  1. Copy the SampleServlet.class file into the doc/WEB-INF/classes directory.
  2. Copy the sample.vm template file into the doc/ directory
  3. Copy the Velocity jar (and any required dependencies - see note above in Tomcat setup section) into the doc/WEB-INF/lib directory.
  4. Start resin.
  5. To access the servlet, point your web browser at :
http://localhost:8080/servlet/SampleServlet
or if that doesn't work :
http://<your computer's ip address>:8080/servlet/SampleServlet
and you should see the output.
Note that this appeared to be a simpler configuration - with the Tomcat example, you set up a complete, new, separate webapp, whereas the Resin instructions don't, although both should provide a sufficient setup to let you play with Velocity.
Note that while we wish we could, we can't answer questions about the servlet engines. Please use the resources provided by the servlet engine provider.
Paw Dybdahl <pdy@csg.csc.dk> contributed this description of using Velocity with WebLogic, as well as some good general suggestions and examples for working with servlets.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值