《Velocity java開發指南》中文版(下)轉載

文章出自:http://sakyone.iteye.com/blog/524292html

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 事件處理器可讓你決定如何處理,其接口代碼以下. java

Java代碼   收藏代碼
  1. public interface NullSetEventHandler extends EventHandler  
  2. {  
  3.     public boolean shouldLogOnNullSet( String lhs, String rhs );  
  4. }  


org.apache.velocity.app.event.ReferenceInsertionEventHandler

A ReferenceInsertionEventHandler 這個事件處理器可讓開發者在引用對象值如($foo)輸出到模板以前截取修改. web

Java代碼   收藏代碼
  1. public interface ReferenceInsertionEventHandler extends EventHandler  
  2. {  
  3.     public Object referenceInsert( String reference, Object value );  
  4. }  

org.apache.velocity.app.event.MethodExceptionEventHandler

當用戶數據對象中的某個命令出錯時, 實現了 MethodExceptionEventHandler接口的事件處理器將被調用以得到具體的命令名字和Exception對象. 事件處理器也能夠重組一個有效的對象返回(通常用於統一的異常處理), 或向它的父類throws一個new Exception, MethodInvocationException接口以下: 數據庫

Java代碼   收藏代碼
  1. public interface MethodExceptionEventHandler extends EventHandler  
  2. {  
  3.     public Object methodException( Class claz, String method, Exception e )  
  4.          throws Exception;  
  5. }  

2.Using the EventCartridge使用事件分發器
能夠直接使用一個事件分發器(EventCartridge),以下例程在org.apache.velocity.test.misc.Test中:
...
apache

Java代碼   收藏代碼
  1. import org.apache.velocity.app.event.EventCartridge;  
  2. import org.apache.velocity.app.event.ReferenceInsertionEventHandler;  
  3. import org.apache.velocity.app.event.MethodExceptionEventHandler;  
  4. import org.apache.velocity.app.event.NullSetEventHandler;  
  5.   
  6. ...  
  7.   
  8. public class Test implements ReferenceInsertionEventHandler,  
  9.                              NullSetEventHandler,  
  10.                              MethodExceptionEventHandler  
  11. {  
  12.     public void myTest()  
  13.     {  
  14.         ....  
  15.   
  16.         /* 
  17.          * now, it's assumed that Test implements the correct methods to 
  18.          * support the event handler interfaces. So to use them, first 
  19.          * make a new cartridge 
  20.          */  
  21.         EventCartridge ec = new EventCartridge();  
  22.   
  23.         /* 
  24.          * then register this class as it contains the handlers 
  25.          */  
  26.         ec.addEventHandler(this);  
  27.   
  28.         /* 
  29.          * and then finally let it attach itself to the context 
  30.          */  
  31.         ec.attachToContext( context );  
  32.   
  33.         /* 
  34.          * now merge your template with the context as you normally 
  35.          * do 
  36.          */  
  37.   
  38.         ....  
  39.     }  
  40.   
  41.     /* 
  42.      * and now the implementations of the event handlers 
  43.      */  
  44.     public Object referenceInsert( String reference, Object value )  
  45.     {  
  46.         /* do something with it */  
  47.         return value;  
  48.     }  
  49.   
  50.     public boolean shouldLogOnNullSet( String lhs, String rhs )  
  51.     {  
  52.         if ( /* whatever rule */ )  
  53.             return false;  
  54.   
  55.         return true;  
  56.     }  
  57.   
  58.     public Object methodException( Class claz, String method, Exception e )  
  59.          throws Exception  
  60.     {  
  61.         if ( /* whatever rule */ )  
  62.            return "I should have thrown";  
  63.   
  64.         throw e;  
  65.     }  
  66. }  


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日誌的例子. api

Java代碼   收藏代碼
  1. import org.apache.velocity.app.VelocityEngine;  
  2. import org.apache.velocity.runtime.RuntimeConstants;  
  3.   
  4. import org.apache.log4j.Category;  
  5. import org.apache.log4j.BasicConfigurator;  
  6.   
  7. public class Log4jCategoryExample  
  8. {  
  9.     public static String CATEGORY_NAME = "velexample";  
  10.   
  11.     public static void main( String args[] )  
  12.         throws Exception  
  13.     {  
  14.         /* 
  15.          * configure log4j to log to console 
  16.          */  
  17.   
  18.         BasicConfigurator.configure();  
  19.   
  20.         Category log = Category.getInstance( CATEGORY_NAME );  
  21.   
  22.         log.info("Hello from Log4jCategoryExample - ready to start velocity");  
  23.   
  24.         /* 
  25.          * now create a new VelocityEngine instance, and 
  26.          * configure it to use the category 
  27.          */  
  28.   
  29.         VelocityEngine ve = new VelocityEngine();  
  30.   
  31.         ve.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,  
  32.             "org.apache.velocity.runtime.log.SimpleLog4JLogSystem" );  
  33.   
  34.         ve.setProperty("runtime.log.logsystem.log4j.category", CATEGORY_NAME);  
  35.   
  36.         ve.init();  
  37.   
  38.         log.info("this should follow the initialization output from velocity");  
  39.     }  
  40. }  

上面的例子能夠在examples/logger_example.下找到.
2.Simple Example of a Custom Logger
這是一個定製實現你本身的日誌記錄器,並將其加入到Velocity的日誌系統中. LogSystem interface—只須要支持這個接口. 緩存

Java代碼   收藏代碼
  1. import org.apache.velocity.runtime.log.LogSystem;  
  2. import org.apache.velocity.runtime.RuntimeServices;  
  3. ...  
  4.   
  5. public class MyClass implements LogSystem  
  6. {  
  7.   
  8. ...  
  9.   
  10.     public MyClass()  
  11.     {  
  12.         ...  
  13.   
  14.         try  
  15.         {  
  16.             /* 
  17.              * register this class as a logger 
  18.              */  
  19.             Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, this );  
  20.             Velocity.init();  
  21.         }  
  22.         catch (Exception e)  
  23.         {  
  24.             /* 
  25.              * do something 
  26.              */  
  27.         }  
  28.     }  
  29.   
  30.     /** 
  31.      * This init() will be invoked once by the LogManager 
  32.      * to give you current RuntimeServices intance 
  33.      */  
  34.     public void init( RuntimeServices rsvc )  
  35.     {  
  36.         // do nothing  
  37.     }  
  38.   
  39.     /** 
  40.      * This is the method that you implement for Velocity to call 
  41.      * with log messages. 
  42.      */  
  43.     public void logVelocityMessage(int level, String message)  
  44.     {  
  45.         /* do something useful */  
  46.     }  
  47. ...  
  48. }  

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配置: tomcat

引用
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 )
encoding 參數能夠設定爲JVM支持的某個值 "UTF-8" or "ISO-8859-1".關於字符集正式的名字, see here.
注意,這僅僅是編碼了模板本身 – 輸出的編碼由應用程序指定.

14.Velocity and XML

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程序以下:
...

Java代碼   收藏代碼
  1. SAXBuilder builder;  
  2. Document root = null;  
  3.   
  4. try  
  5. {  
  6.     builder = new SAXBuilder( "org.apache.xerces.parsers.SAXParser" );  
  7.     root = builder.build("test.xml");  
  8. }  
  9. catch( Exception ee)  
  10. {}  
  11.   
  12. VelocityContext vc = new VelocityContext();  
  13. vc.put("root", root );  
  14.   
  15. ...  


(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


15.FAQ (Frequently Asked Questions)
開發中常見的問題解答.
1.Why Can't I Access Class Members and Constants from VTL?
在VTL中沒法訪問到類的數據域
最簡單的緣由是咱們沒法反射/內省(introspect )這個對象.由於就OOP來講,對象中要隱藏本身沒有必要外露的數據或命令.解決方法:包狀成publicly 命令反回它,保證它是公開訪問的. 固然,你要保證能改動源文件, 不然,就要用工具來解析它. org.apache.velocity.app.FieldMethodizer是用來解析你的類的, 以下示例如何將一個public static fields 導出到模板中.假設你的類是 :

Java代碼   收藏代碼
  1. public class Foo  
  2.     {  
  3.         public static String PATH_ROOT = "/foo/bar";  
  4.   
  5.         ....  
  6.     }  


你可這樣將它放入context中:
context.put("myfoo", new FieldMethodizer( new Foo() ) );

而後在模板中就能夠java代碼的風格來訪問 :
$myfoo.PATH_ROOT

若是你須要訪問public的非靜態域時(public non-static members)甚止是私有成員!那你就必須擴展或重寫 FieldMethodizer 這個類----但你爲何要搞得這麼複雜呢?
2.Where does Velocity look for Templates?
Velocity到哪裏提取模板文件?
默認的,不作任何配置更改的狀況下,Velocity會在當前目錄下或相對與當前目錄(如'foo/bar.vm')下查找.
Velocity對這些都是自動處理的. Velocity只記住它本身的一個root目錄,這個概念不一樣與多根目錄的文件系統(like - "C:\", "D:\", etc).

16.Summary
但願這個指南能幫助您出色的將velocity應用到項目中. 請將您的意見反饋發送到mail lists.


17.Appendix 1 : Deploying the Example Servlet
佈署本文中的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.因此,如下是咱們要作的:
首先,建立一個新的 'webapp' 暫時名叫 velexample 放到Tomcat的webapps 目錄下, 這個新的目錄結構以下 :

引用
velexample
velexample/WEB-INF
velexample/WEB-INF/lib
velexample/WEB-INF/classes

將Velocity jar 放到velexample/WEB-INF/lib下. (從1.2版本後,全部相關依賴包都打包在. velocity-dep-1.2.jar中),固然,相關的依賴包也必須放到WEB-INF/lib下. 具體能夠看 "Getting Started" and "Dependencies", 這兩節的介紹. 將編譯過的SampleServlet.class放到 velexample/WEB-INF/classes 下. 將sample.vm 放到目錄velexample 下. 如今就能夠啓動servlet來訪問servlet了. 在Browser中輸出以下 : http://localhost:8080/velexample/servlet/SampleServlet 如不能工做,則試下 : http://<your computer's ip address>:8080/velexample/servlet/SampleServlet 看到輸出結果了嗎?

相關文章
相關標籤/搜索