查看文章 |
8.Application Attributes 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(事件分发和处理) 1.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; } 2.Using the EventCartridge使用事件分发器 可以直接使用一个事件分发器(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的进一步说明. 以下,是默认配置的说明: 1.Runtime Log 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 当一个引用无效时,打开日志输出. 在生产系统运行中,这很有效,也是很有用的调试工具. 2.字符集编码问题 input.encoding = ISO-8859-1 输出模板的编码方式 (templates). 你可选择对你模板的编码方式,如UTF-8.GBK. output.encoding = ISO-8859-1 VelocityServlet 对输出流(output streams)的编码方式. 3.#foreach() Directive directive.foreach.counter.name = velocityCount 在模板中使用#foreach() 指令时,这里设定的字符串名字将做为context key 代表循环中的计数器名,如以上设定,在模板中可以通过 $velocityCount来访问. directive.foreach.counter.initial.value = 1 #foreach() 中计数器的起始值. 4.#include() and #parse() Directive directive.include.output.errormsg.start = directive.include.output.errormsg.end = 使用#include()时,定义内部流中开始和结束的错误消息标记,如果两者都设这屯,错误消息将被输出到流中'.但必须是两都定义. directive.parse.maxdepth = 10 定义模板的解析深度,当在一个模板中用#parse()指示解析另外一个模板时,这个值可以防止解析时出现recursion解析. 5.资源管理 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 6.Velocimacro(宏配置) 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的设置一样,主要是为方便开发调试用. 7.语义更改 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. 8.运行时配置 parser.pool.size = 20 控制Velocity启动是需要创建并放到池中预备使用的模板解析器的个数----这只是预装. 默认的20个对一般用户来说足够了. 即使这个值小了,Velocity也会运行时根据系统需要动态增加(但增加的不会装入池中). 新增时会在日志中输出信息 11.Configuring the Log System(日志记录配置) Velocity有很容易扩展的日志系统.即使不做任何设置,velocity也会将日志输出到当前目录下的 velocity.log文件中. 对一些高级用户, 可以很方便的将你当前系统的日志和它整合起来. 从1.3开始, Velocity 默认使用 Jakarta Avalon Logkit logger做为日志记录器,也可以用 Jakarta Log4j logger.首先它会在classpath中查找Logkit. 找不到,会再尝试Log4j. 1.一般的可选日志功能: 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的值, Velocity在init()时将创建你的日志实例. 更多相关信息可以看 Velocity helper class 和 configuration keys and values. 要注意的是, 接口org.apache.velocity.runtime.log.LogSystem 在1.2后才支持这一功能. Integrated Logging 你可以将Velocity的日志和你现存系统的日志整合到一起. Using Log4j With Existing Category 这里是一个使用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.下找到. 2.Simple Example of a Custom Logger 这是一个定制实现你自己的日志记录器,并将其加入到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(资源装载器配置) 1.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将从classpath中load 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 target为jar-j2ee,更细说明请见文档中对类 org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader的介绍. 2.Configuration Examples 己配置的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' 这三个名字不是固定是,可以根据你的喜好来设定. 但只要保持上面的对应关系就是. 3.插入定制资源管理器和Cache实现 资源管理器是相关资源 (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 设定 13.Template Encoding for Internationalization(字符编码和国际化) 从版本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 ) |