Velocity初始化過程解析


velocity就是由templateenginecontext組成。

1、首先創建一個template(如果是用在web上就是一個html文件),將需要參數化或實例化的地方用跟context有關的符號標記出來,標記時用velocity template language。而template應該可以是任意的文本。

2、給context設定一些值,這些值用來替換在template中被標記的地方。

3、利用enginetemplate中需要替換的地方用context中的值替換掉,也就是所謂的merge,從而得到該模板的實例。

 

Velocity的初始化有多種方式:

 

1init()

 

2init(Properties p)

 

3init(String propertiesName) 

 

第一種init()方式是最簡單的方式,當我們的程序沒有配置類似velocity.properties這樣的文件的時候,就會使用默認的配置文件來初始化,

默認的配置文件的位置在org/apache/velocity/runtime/defaults/velocity.properties

 

應用在WEB的時候,默認的配置文件使用的是org/apache/velocity/tools/view/servlet/velocity.properties

 

在初始化前,velocity會把配置文件的屬性和值讀取后保存在內存中,初始化時,velocity將會初始化以下幾個方面:

 

 

  1. Logging System 日志系統
  2. ResourceManager 資源加載器
  3. EventHandler 事件句柄
  4. Parser Pool 解析池
  5. Global Cache 全局緩存
  6. Velocimacro System 宏

Logging System

 

 

velocity會根據配置文件里的信息,查找一個名叫runtime.log.logsystem的屬性,一旦配置文件中有配置這個屬性,則會開始去創建日志系統。當velocity沒有配置runtime.log.logsystem這個屬性的時候,則會繼續尋找runtime.log.logsystem.class這個屬性,默認的velocity.properties配置文件中,這個屬性的值按順序依次為

 

  1. AvalonLogChute
  2. Log4JLogChute
  3. CommonsLogLogChute
  4. ServletLogChute
  5. JdkLogChute

 

當然,velocity不會使用那么多個日志系統,只會使用第一個能實例化的日志系統。如果之前的創建工作都失敗的話,那么意味着用戶沒有設置值或者是沒有找到類,velocity將會使用系統統默認的SystemLogChute來輸出日志,這個日志系統使用System.err方式輸出日志。一旦使用runtime.log.logsystem或者runtime.log.logsystem.class屬性創建日志系統成功后,velocity就會把HoldingLogChute替換成新的日志系統。這樣,日志的初始化才真正的結束。

 

ResourceManager 

 

資源加載器是velocity加載資源使用的一個工具。Velocity的配置文件里有個屬性叫Resource.manager.class,默認的classorg.apache.velocity.runtime.resource.ResourceManagerImpl。Velocity會嘗試初始化ResourceManagerImpl,其中會查找resource.loader這個屬性,resource.loader這個屬性是可以有多個的,每個Loader都會生效。

ResourceLoader一共有7種:

  1. ClasspathResourceLoader
  2. DataSourceResourceLoader
  3. FileResourceLoader
  4. JarResourceLoader
  5. StringResourceLoader
  6. URLResourceLoader
  7. WebappLoader 

默認的是第3FileResourceLoader。除了第7webappLoadervelocity-tools包作為velocity的附屬工具后來添加的,其余6個都velocity包自帶的,如果覺得這些都不適用,你也可以自己實現一個。實現一個資源加載器只要繼承ResourceLoader,實現它的幾個方法就可以了。所謂的資源加載器指的就是velocity讀取文件的方法,有直接從文件讀取的,有從jar包中讀取的,也有從類路徑中讀取的,基本上只要自己重寫getResourceStream方法就可以。在初始化的過程中,會讀取resource.manager.logwhenfoundresource.manager.cache.class這兩個屬性,同時,也會進行資源緩存的初始化操作。

EventHandler 

 

 

用戶可以自定義響應的事件,Velocity提供了對模板解析過程事件的處理,用戶可以響應模板產生的事件。 

 

org.apache.velocity.app.event.EventHandler,是一個最簡單的接口。我們可以通過實現這個接口來處理頁面上不同的信息。

 

1)IncludeEventHandler

 

在使用#include(),#parse()語法的時候,允許開發修改include或者parse文件的路徑(一般用於資源找不到的情況)

 

IncludeEventHandler有兩個實現類,分別是IncludeNotFoundIncludeRelativePath

 

當找不到#include指令的文件時,IncludeNotFound類會去做一些處理,例如去增加一個eventhandler.include.notfound=notfound.vm的配置,當然,如果不存在notfound.vm,也會給出"Can't find include not found page"的提示。

 

2)InvalidReferenceEventHandler

 

當渲染頁面的時候,一旦遇到非法的reference,就會觸發此事件。開發者可以偵聽此事件,用於錯誤的報告,或者修改返回的內容。

 

ReportInvalidReferences是它的一個實現類,用於報告無效的refenrences。如果在velocity的配置文件中使用了eventhandler.invalidreference.exception=true配置,在運行過程中碰到第一個無效的refenrences就會拋出ParseErrorRuntimeException異常,執行暫停。如果配置為false的話,則會將錯誤先收在InvalidReferenceInfo列表對象中,運行照舊。

 

3)MethodExceptionEventHandler

 

渲染模板,一旦發現調用的方法拋出異常的時候,就會觸發此事件。允許開發者處理這個異常,輸出友好信息或者拋出異常。必須返回一個值用於模板的渲染。 

 

4)NullSetEventHandler

 

當使用#set()語法,設置一個null值的時候,會觸發此事件。目前Velocity官方沒有提供默認實現

 

5)ReferenceInsertionEventHandler

 

當渲染變量(reference)的時候,就會觸發此事件。允許開發者返回更加友好的值--一般用於內容的escape,比如HtmlEscape等。

Parser Pool

 

 

Velocity會使用類似線程池的機制解析頁面。配置的keyparser.pool.classparser.pool.size。默認的實現類為org.apache.velocity.util.SimplePoolVelocity。

 

velocity啟動時需要創建模板解析器的個數默認為20,對一般用戶來說足夠了即使這個值小了,Velocity也會運行時根據系統需要動態增加(但增加的不會裝入解析池中). 新增時會在日志中輸出信息

Global Cache 全局緩存

開啟全局緩存配置項  file.resource.loader.cache=true file.resource.loader.modificationCheckInterval=-1

Template t = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, finalLocation, encoding);  
  
VelocityResult.java :  
protected Template getTemplate(ValueStack stack, VelocityEngine velocity, ActionInvocation invocation, String location, String encoding) throws Exception {  
        if (!location.startsWith("/")) {  
            location = invocation.getProxy().getNamespace() + "/" + location;  
        }  
  
        Template template = velocity.getTemplate(location, encoding);  
  
        return template;  
    }  
  
VelocityEngine.java  
public Template getTemplate(String name, String encoding)  
        throws ResourceNotFoundException, ParseErrorException, Exception  
    {  
        return ri.getTemplate( name, encoding );  
    }  
  
RuntimeInstance.java  
public Template getTemplate(String name, String  encoding)  
        throws ResourceNotFoundException, ParseErrorException, Exception  
    {  
        requireInitialization();  
  
        return (Template)  
                resourceManager.getResource(name,  
                    ResourceManager.RESOURCE_TEMPLATE, encoding);  
    }  
  
ResourceManagerImpl.java  
public Resource getResource(final String resourceName, final int resourceType, final String encoding)  
        throws ResourceNotFoundException,  
            ParseErrorException,  
            Exception  
    {  
        String resourceKey = resourceType + resourceName;  
        Resource resource = globalCache.get(resourceKey);  
  
ResourceCacheImpl.java  
public Resource get( Object key )  
    {  
        return (Resource) cache.get( key );  
    }  

 

 

 

 

 

Velocimacro(宏配置)

 

Velocity engine運行時,會載入一個全局的宏文件。所有模板都可訪問該宏文件(Velocimacros). 這個文件位置在相對於資源文件的根目錄下velocity默認的配置項為velocimacro.library=VM_global_library.vm。此外,還有一些其他配置來處理宏的不同使用情況,例如:

 

velocimacro.permissions.allow.inline=true定義在模板中是否可用#macro()指令定義一個新的宏。默認為true,表示所有的vm都可以新建宏,但是要注意可能會把全局的宏配置給替換掉。

 

velocimacro.permissions.allow.inline.to.replace.global=false控制用戶定義的宏是否可以可以替換Velocity全局宏。

 

velocimacro.library.autoreload=false控制宏是否自動載入。當值為true宏將根據是否修改而決定是否需要重新加載,這個特性可在調試時很方便,不需重啟你的服務器。 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM