Change Dir

          先知cd——熱愛生活是一切藝術(shù)的開始

          統(tǒng)計(jì)

          留言簿(18)

          積分與排名

          “牛”們的博客

          各個(gè)公司技術(shù)

          我的鏈接

          淘寶技術(shù)

          閱讀排行榜

          評(píng)論排行榜

          velocity學(xué)習(xí)筆記(上)

           

          Velocity筆記(上)

          雜七雜八的看了一些velocity的資料,把所見所得做個(gè)簡(jiǎn)單不系統(tǒng)的筆記寫下來,算是增強(qiáng)記憶。

          動(dòng)態(tài)語言的特性:

          動(dòng)態(tài)語言需要一個(gè)解釋器,而這個(gè)解釋器一般在服務(wù)器中。

          MVC

          Model:系統(tǒng)和應(yīng)用的狀態(tài)表示,一般是類或者其他數(shù)據(jù)結(jié)構(gòu)。可以改變系統(tǒng)狀態(tài)的Actionsmethod。典型的javabean。設(shè)計(jì)初衷就是為了數(shù)據(jù)和顯示的分離

          View:顯示結(jié)果數(shù)據(jù)的組成部分,隨著model的不同以及狀態(tài)改變,view也要相應(yīng)的做出變化。

          Controller:用戶和應(yīng)用之間交互的橋梁。Controller捕獲用戶的輸入,并利用既定邏輯決定將這些命令輸入路由到哪一個(gè)model進(jìn)行處理。

          只使用jsp技術(shù)叫做model 1

          加入servlet后叫做model 2

          什么是Velocity

          Velocity is a template language designed to give Web designers an easy way to

          present dynamic information to users of a Web site or application.

          Velocity有個(gè)集合叫做context,說白了就是controllermodel層的封裝,提供了網(wǎng)頁模板。

          實(shí)現(xiàn)了velocity的代碼將利用從context中的對(duì)象里獲取的數(shù)據(jù)替換模板中的腳本元素。

          Velocity的使用簡(jiǎn)單代碼:

          一個(gè)簡(jiǎn)單的語言描述過程就是:將velocity初始化并在contextput進(jìn)去對(duì)象,然后template加載某個(gè)vm模板,然后用template將這個(gè)vmcontext進(jìn)行merge,就生成了view頁面了。

          Context可以把其他類型的數(shù)據(jù)put進(jìn)來,velocity會(huì)自動(dòng)的調(diào)用這些對(duì)象的toString方法。

          下面重點(diǎn)說說context

          Context介紹

          Context本質(zhì)上是一個(gè)介于java代碼層和velocity模板層之間的一個(gè)數(shù)據(jù)橋梁。Java開發(fā)人員將各種各樣的數(shù)據(jù)對(duì)象放到context中,頁面模板設(shè)計(jì)人員從context取得這些對(duì)象的referenceVelocity中定義了VelocityContext來提供基本實(shí)現(xiàn)。這個(gè)實(shí)現(xiàn)與java中的hashtable類似,最有用和常用的方法就是

          Public Object put(String key, Object value);

          Public Object get(String key);

          如果理解了context的容器特性,那么什么東西能放進(jìn)去呢?context首先支持放一些迭代對(duì)象(Iterative Objects),比如對(duì)象數(shù)組Object[], java.util.Collection, java.util.Map, java.util.Iterator, java.util.Enumeration, 以及任意的有public Iterator iterator()方法的public class。其次context還支持put靜態(tài)類(static class),比如context.put(“Math”, Math.class)。當(dāng)然,在velocity運(yùn)行時(shí)模板 產(chǎn)生的對(duì)象也可以放到context中。

          Velocity的三種reference

          變量variable:對(duì)應(yīng)java對(duì)象的一種字符串化的表示,它返回的值是調(diào)用了javatoString方法后的結(jié)果。

          方法method:調(diào)用所引用對(duì)象的某個(gè)方法,該方法必須是public類的一個(gè)public方法。如果該方法有返回值,那么velocity在調(diào)用完方法后會(huì)同樣的對(duì)返回值進(jìn)行toString包裝。對(duì)參數(shù)的要求是velocity要求所有的方法參數(shù)也必須是string的。

          屬性property:類似方法,除了訪問java類的屬性外,還等價(jià)于get***方法。

          $!前綴是quiet notation符號(hào),用這個(gè)前綴產(chǎn)生的引用在引用對(duì)象不存在的時(shí)候,會(huì)返回“”字符串而不是不存在的對(duì)象的名字的字符串。

          "”是轉(zhuǎn)義字符,可以轉(zhuǎn)義$符號(hào)和其他符號(hào)

          Velocity指令

          #stop:用于debug,當(dāng)engine遇到這個(gè)指令,就會(huì)停止執(zhí)行,并將控制權(quán)返回給調(diào)用程序。

          #include:用于包含外部文件,將外部文件的內(nèi)容直接加入程序中。

          #parse:與include類似,但是不同之處在于,include引入的是靜態(tài)的文件,而parse會(huì)動(dòng)態(tài)的加載模板,也就是說,parse會(huì)解析vm文件,然后再加入到源文件中去。

          #set:就是一個(gè)很強(qiáng)大的賦值指令,不管被賦值的變量是否已經(jīng)存在或賦值,新的set指令會(huì)完全覆蓋。指令格式就是#set(ref=value)。幾個(gè)值得注意的set用法如下

          Listrange的用法可以等同的看做是java里的ArrayList

          對(duì)boolean值的setset支持短路short circuit,具體代碼見下:

          #end:聲明一個(gè)程序塊的結(jié)束,必須以#if或者#foreach或者#macro開始。

          #if:就是普通的if,只不過在#if中,條件表達(dá)式里用true表示真,用false表示假,沒有null表達(dá)式。測(cè)試null的話直接用#if($condition)指令即可。常用的邏輯操作符(&&||!)都可以使用,比較操作符也與java相同。

          #else:接著#if的使用指令,邏輯分支,同java等其他語言的邏輯一樣。有一點(diǎn)需要注意,沒有#else#if需要#end,有了#else,那么#end加在#else后即可,#if后不需要再加#end。如:

          #elseif:就是多分支情況下的else if合寫。對(duì)#end的要求同#else

          #foreach:直接用例子解釋:

          當(dāng)然需要補(bǔ)充一點(diǎn)的是,這個(gè)循環(huán)訪問的list的生成不僅可以在頁面中定義,如上例,也可以在context中產(chǎn)生,比如在put的時(shí)候就把javaarray或者實(shí)現(xiàn)了集合類的map,collectionput進(jìn)去。當(dāng)然,直接foreach一個(gè)map,那么就是訪問的mapvalue,想訪問它的key的話需要調(diào)用該mapkeySet方法得到setForeach的內(nèi)置循環(huán)增量叫做$velocityCount

          #macro:就是velocity里對(duì)于c語言中的宏的概念,注意不是函數(shù),功能雖然類似,但是macro是在運(yùn)行時(shí)之前就確定好的,因此用#parse解析無效。語法就是#macro(name $param1 $param2)這樣的樣式,其中name是宏的名字,后面的param是參數(shù)。調(diào)用時(shí)候的參數(shù)的個(gè)數(shù)一定要與聲明的匹配,velocity不提供默認(rèn)參數(shù)和重載實(shí)現(xiàn)。參數(shù)類型可以是字符串,數(shù)字常量,booleanrange操作符,數(shù)組列表和velocity引用。

          想定義一個(gè)全部vm通用的宏,那么要把它放在VM_global_library.vm里。

          Velocimacro properties

          Velocimacro.library:聲明組成velocimacro library的文件名。默認(rèn)是VM_global_library.vm

          Velocimacro.permissions.allow.inline:如果設(shè)置這個(gè)屬性為false,那么內(nèi)聯(lián)的macro聲明將不被引擎執(zhí)行。默認(rèn)是true的。

          Velocimacro.permissions.allow.inline.to.replace.global:聲明一個(gè)內(nèi)聯(lián)的macro是否可以override一個(gè)library提供的macro。默認(rèn)是false

          Velocimacro. permissions.allow.inline.local.scope:聲明模板是否可以提供私有的關(guān)于velocimacro的命名空間。一旦被設(shè)置為true,那么內(nèi)聯(lián)的macro只可以被本模板看到。默認(rèn)是false

          Velocimacro.context.localscope:聲明在使用velocimacro時(shí)#set指令所影響的velocitycontext的行為(好蹩腳)。就是說,一旦設(shè)置這個(gè)屬性為truevelocimacro只接受本地的context。調(diào)用者注入到context中的對(duì)象將不被看到。默認(rèn)是false

          Velocimacro.library.autoreload:聲明一個(gè)修改后的velocimacro library是否在macro被調(diào)用時(shí)自動(dòng)reload。默認(rèn)是false

          Velocimacro.messages.on:聲明是否由引擎產(chǎn)生額外的log信息,默認(rèn)是true

          遞歸和嵌套macro都是允許的,但是遞歸的方法是不推薦的。

          下面是講velocity是如何開始作用的:

          通過調(diào)用Velocity.init()這個(gè)靜態(tài)方法,我們初始化了runtime。這個(gè)調(diào)用的結(jié)果就是運(yùn)行時(shí)的引擎通過讀取org/apache/velocity/runtime/defaults/velocity.properties文件被初始化。Velocity提供了3種定制技術(shù)去定制runtime configuration

          第一種技術(shù):自定義一個(gè)properties文件,然后通過init的帶參數(shù)方法初始化velocity引擎。

          第二種技術(shù):在運(yùn)行時(shí)構(gòu)建一個(gè)javaProperties對(duì)象,然后通過set方法注入屬性,在程序代碼中傳遞給init參數(shù)。

          第三種技術(shù):為了更細(xì)粒度的控制velocity引擎的初始化,一些細(xì)節(jié)的實(shí)現(xiàn)就是可以利用velocity自己的一些靜態(tài)方法在init之前去修改屬性文件。比如Velocity.setProperty(String propertyName, String value)

          更多的屬性:

          Directive類的

          Directive.foreach.counter.name:聲明了foreach循環(huán)中的循環(huán)變量名字,默認(rèn)是velocityCount

          Directive.foreach.counter.initial.value:聲明了循環(huán)時(shí)循環(huán)變量的初始值,默認(rèn)是1,雖然C系語言的初始值都為0.

          Directive.include.output.errormsg.start:聲明了在include調(diào)用時(shí)輸入錯(cuò)誤參數(shù)所顯示的出錯(cuò)提示文本的開頭,默認(rèn)是“<!—include error:”。

          Directive.include.output.errormsg.end:同上,代表了結(jié)尾,默認(rèn)值是“see error log -->

          Directive.parse.max.depth:這個(gè)聲明了parse命令的最大嵌套深度。默認(rèn)是10.

          Encoding類的

          Input.encoding:聲明被模板引擎處理的模板的編碼,默認(rèn)是ISO-8859-1.

          Output.encoding:聲明關(guān)聯(lián)到輸出流的編碼,默認(rèn)是ISO-8859-1

          Logging類的

          Runtime.log:聲明velocitylog文件所在的路徑,默認(rèn)是velocity.log

          Runtime.log.logsystem:聲明velocitylog任務(wù)系統(tǒng),設(shè)置的值需要實(shí)現(xiàn)org.apache.velocity.runtime.log.LogSystem接口。無默認(rèn)值。

          Runtime.log.logsystem.class:聲明velocity運(yùn)行時(shí)用于處理logging服務(wù)的類名,包含一系列用逗號(hào)隔開的列表。默認(rèn)值是runtime.log.logsystem.class property is org.apache.velocity.

          runtime.log.AvalonLogSystem,org.apache.velocity.runtime.log.SimpleLog4J

          logSystem. Logging may be disabled by providing a value of org.apache.velocity.

          runtime.log.NullLogSystem

          runtime.log.error.stacktrace

          runtime.log.warn.stacktrace

          runtime.log.info.stacktrace:這三個(gè)分別用來聲明運(yùn)行時(shí)引擎在記錄錯(cuò)誤、警告和信息消息時(shí)是否開啟stacktrace。默認(rèn)值都是false

          Runtime.log.invalid.references:聲明非法引用在模板中發(fā)現(xiàn)時(shí)是否記錄的標(biāo)記,默認(rèn)是true

          Resource Management類的

          Resource.manager.class:聲明處理velocity資源管理任務(wù)的類,該類必須實(shí)現(xiàn)org.apache.velocity.runtime.resource.ResourceManager接口。默認(rèn)值是org.apache.velocity.runtime.resource.ResourceManagerImpl

          Resource.manager.cache.class:聲明了資源管理緩存請(qǐng)求的類,該類必須實(shí)現(xiàn)org.apache.velocity.runtime.resource.ResourceCache接口。默認(rèn)是org.apache.velocity.runtime.resource.ResourceCacheImpl

          Resource.manager.logwhenfound:聲明了資源管理在第一次定位資源時(shí)是否記錄log。默認(rèn)是true

          Resource.loader:關(guān)聯(lián)一個(gè)名字給指定的resource loader

          <loader>.resource.loader.description:聲明了resource loader的文字描述。

          <loader>.resource.loader.class:聲明了用于初始化加載關(guān)聯(lián)資源類型的類,該類需要繼承org.apache.velocity.runtime.resource.loader.ResourceLoader類,并且提供特定功能的資源類型。Velocity.properties提供了一個(gè)org.apache.velocity.runtime.resource.loader.FileResourceLoader的類。

          <loader>.resource.loader.path:聲明了一個(gè)根目錄用來存放相關(guān)類型的資源。Velocity.properties提供了.作為根目錄。

          <loader>.resource.loader.cache:聲明loader是否要緩存特定資源。一般建議true

          <loader>.resource.loader.modificationCheckInterval:聲明了檢查緩存資源是否有修改的時(shí)間間隔,以秒為單位。默認(rèn)是2.

          其他類的

          Runtime.initerpolate.string.literals:聲明了模板引擎是否要插入字符串常量,默認(rèn)是true

          Parser.pool.size:聲明了啟動(dòng)時(shí)runtime創(chuàng)建的parser pool的大小,默認(rèn)是20.

          Resource loaders資源加載

          一個(gè)velocityresource簡(jiǎn)單說就是一個(gè)提供給模板引擎的輸入。包括正規(guī)模板、velocimacrolibrary、由include指令引入的普通文本。一個(gè)resource loader就是一個(gè)知道如何從這些特定的resource中提取資源的實(shí)體。一般用到的就是file resource loader,當(dāng)然velocity還提供了3種其他loader類型:JAR, ClasspathDataSource

          Events事件

          為了提供模板處理時(shí)的更好控制,velocity提供了事件處理等級(jí),支持用戶干預(yù)。

          有三種事件類型:

          第一,   #set指令中為引用賦NULL的時(shí)候。

          第二,   Java方法調(diào)用velocity方法或?qū)傩砸贸霈F(xiàn)異常的時(shí)候。

          第三,   每次velocity引用對(duì)應(yīng)的值插入輸出流的時(shí)候。

          Velocity提供了NullSetEventHandler, MethodExceptionEventHandlerReferenceInsertionEventHandler接口去處理這些事件。

          Context chaining

          簡(jiǎn)單講就是一層層的包裝context(直覺讓我想起façade模式),如果有重復(fù)的話,最外層的覆蓋最里層的,但是本層的context對(duì)于重復(fù)的key還是可以保持可訪問。實(shí)現(xiàn)方式是通過VelocityContext的重載構(gòu)造方法。

          VelocityXML

          velocity支持對(duì)xml的處理,只要加入類似這樣的代碼即可

          接著在displayxml.vm這樣寫:

          然后就可以咯。

          如何輸出XML與輸出HTML是一致的。

          結(jié)合velocityservlet

          其實(shí)很簡(jiǎn)單,寫一個(gè)類,繼承VelocityServlet。不需要普通的doGetdoPost方法,取而代之的是一個(gè)handleRequest方法,該方法傳遞3個(gè)參數(shù),HttpServletRequest, HttpServletResponseContext。前兩個(gè)參數(shù)與普通的servlet一樣,最后一個(gè)參數(shù)就對(duì)應(yīng)了velocity模板引擎的context。該方法返回一個(gè)Template。基礎(chǔ)代碼如下:

          HttpServletRequestHttpServletResponsecontext中同樣存在,名字分別是reqres,我們可以寫這樣的代碼去訪問和讀取requestresponse

          #set($username = $req.getParameter(‘username’))

          VelocityServlet非常強(qiáng)大,除了簡(jiǎn)單的handleRequest方法外,還包括了一系列方法:

          Properties loadConfiguration(ServletConfig):允許添加額外的servlet屬性。

          Context createContext(HttpServletRequest, HttpServletResponse):允許開發(fā)者創(chuàng)建自己的context,這個(gè)context可以進(jìn)行似有的merge

          void setContentType( HttpServletRequest,HttpServletResponse):設(shè)置內(nèi)容類型,默認(rèn)的是text/html格式。

          void mergeTemplate(Template, Context, HttpServletResponse):自行控制合并模板的方法,可以繞過handleRequest

          void requestCleanup(HttpServletRequest, HttpServletResponse,Context):自行合并后的清理操作。

          protected void error(HttpServletRequest, HttpServletResponse, Exception):錯(cuò)誤處理。

          Velocityturbine的結(jié)合

          可以說turbinevelocity的最好舞臺(tái),它天然的結(jié)合了velocity

          Turbine的三個(gè)特性:

          1.       基于servlet作為控制器

          2.       強(qiáng)調(diào)安全繼承

          3.       獨(dú)立于web使用。

          TurbineMVC經(jīng)典組合就是EJB作為模型,servlet寫控制器,而velocity是顯示。

          先看看turbine的架構(gòu):

          5大模塊,都在assembler下面。其中

          Action:完成特定任務(wù)的代碼。

          Navigation:用來顯示導(dǎo)航鏈接和控制的velocity模板。

          Screenvelocity模板和java類的組合,用來顯示layout模塊內(nèi)的核心內(nèi)容。

          Layoutvelocity模板,用來描述頁面如何工作。

          Page:一個(gè)包含了所有這些模塊的概念級(jí)別的對(duì)象。

          先來看看action模塊:

          這個(gè)圖是action和其他模塊之間的一個(gè)流動(dòng)視圖。當(dāng)有一個(gè)get或者post請(qǐng)求時(shí),page模塊將執(zhí)行action模塊,由action模塊判斷由哪個(gè)screen來顯示信息。

          Navigation模塊:

          說白了就是webx中的control,控制頁面的上下左右各個(gè)部分,表達(dá)不同的所謂navigation schemes。這個(gè)模塊是被layout執(zhí)行的。

          Screen模塊:

          Navigation模塊展示了頁面的各個(gè)邊緣組成,那么screen就負(fù)責(zé)顯示頁面的核心內(nèi)容。

          Layout模塊:

          Layout如其名,就是通過布局來控制哪里安排navigation,哪里顯示screen

          Page模塊:

          Page是整個(gè)web應(yīng)用的外殼,請(qǐng)求也是先到達(dá)page的。Page更像一個(gè)容器,用來管理和聯(lián)系整個(gè)的各個(gè)模塊。


          這個(gè)圖顯示了各個(gè)模塊的包裝關(guān)系。

          Turbine定義了5個(gè)loader去加載這5個(gè)模塊,loader的結(jié)構(gòu)圖如下:


          未完待續(xù)~~

          參考資料:

          http://velocity.apache.org/里的user guidedeveloper guide

          Wiley - Mastering Apache Velocity》,Joseph D. Gradecki, Jim Cole

          posted on 2011-04-07 11:03 changedi 閱讀(10036) 評(píng)論(1)  編輯  收藏 所屬分類: Java技術(shù)

          評(píng)論

          # re: velocity學(xué)習(xí)筆記(上) 2013-07-26 17:42 VAllen

          只能說Java版的Velocity太棒了。
          而.NET版的NVelocity依然有很多不足之處。
          其次context還支持put靜態(tài)類(static class),比如context.put(“Math”, Math.class)..
          我想put一個(gè)靜態(tài)類都做不到,杯具~~
          如有解決方案,請(qǐng)電郵caizz@vip.qq.com,感激不盡~  回復(fù)  更多評(píng)論   

          主站蜘蛛池模板: 扬州市| 新乡县| 乐平市| 依兰县| 五莲县| 仙居县| 西宁市| 镇江市| 乐平市| 星子县| 祁东县| 白玉县| 千阳县| 四平市| 孟州市| 临泉县| 洪洞县| 敦化市| 徐汇区| 天长市| 凤山市| 温宿县| 利川市| 江西省| 玛纳斯县| 沁水县| 江孜县| 通山县| 门头沟区| 湖南省| 山阴县| 砀山县| 勐海县| 惠安县| 建始县| 高唐县| 庆阳市| 景谷| 余姚市| 靖西县| 中山市|