Velocity空間

          快速構(gòu)建JAVA應(yīng)用
          隨筆 - 11, 文章 - 15, 評論 - 5, 引用 - 0
          數(shù)據(jù)加載中……

          CHAPTER 5 構(gòu)建Hello World示例

           

          目前,你已經(jīng)對Velocity有了一個很好的理解,并且理解了MVC是如何工作的,同時也搭建一個Velocity的工作環(huán)境,是時候開始學(xué)習(xí)如何Velocity了。正如你所期望的一樣,第一個示例就是Hello World

          Hello World!

          首先,你需要確定HTML頁面的Hello World模板和在頁面上顯示些什么信息。如果我們僅僅簡單的輸出“Hello World”,這就不能很好體現(xiàn)Velocity的特性。因此,我們準(zhǔn)備生成一個模板,輸出內(nèi)容為:“Hello World, Sam is Here”,在這里,“Sam”用的是引用值。

          現(xiàn)在,你已經(jīng)知道了頁面需要輸出的內(nèi)容,接下來,你需要和JAVA開發(fā)者一起討論并確定頁面所需要引用對象的名稱(此處的引用對象是“Sam”),在這里我們將這個引用對象的名稱約定為“name”。在構(gòu)建Hello World示例時,你需要考慮以下三個版本:

          不使用上下文的Velocity模板

          使用上下文的Velocity模板

          使用WEBVelocity模板

          如果你已經(jīng)非常熟悉服務(wù)器端語言,比如PHP,你或許會非常驚奇,在Velocity模板被瀏覽時,我們?yōu)槭裁床挥懻?/span>WEB服務(wù)器的解釋程序。這是因?yàn)?/span>Velocity并不含解釋程序,它是純JAVA語言,屬性編譯運(yùn)行方式,而非解釋運(yùn)行方式。所有在模板和上下文之間的合并處理都是通過JAVA代碼來完成的。這些JAVA代碼可能存在于Servlet中,也可嵌入JSP或應(yīng)用程序中。

          WEB中使用Velocity時,很多情況下是使用Servlet來處理模板轉(zhuǎn)換工作的。

          不使用上下文的Velocity模板

          Hello World示例代碼見Listing 5.1,它使用Velocity指令語句#set來為模板中引用指定一個值(在模板中使用),同時使用嵌入Hello World文本的$name指令來引用#set指定的值。

          這個示例比較容易理解,在Velocity對模板進(jìn)行解析時,如果是普通的文本,則忽略,直接輸出;當(dāng)遇到#set指令時,它就創(chuàng)建一個名叫$name的內(nèi)部變量(在模板文件中指定的),并賦值為"Sam"(在模板文件中指定的);接著,程序?qū)⒅苯虞敵?/span>“Hello World”文本;在系統(tǒng)處理到$name引用時,系統(tǒng)將嘗試在上下文中查找一個名叫$name的對象,如果在上下文中沒有匹配的對象,系統(tǒng)將嘗試匹配之前用#set創(chuàng)建的引用。

          #set( $name = "Sam" )

          Hello World, $name is Here

          Listing 5.1 The Velocity Hello World template.

          當(dāng)然,僅僅擁有一個模板是不能工作的,你還需要一個把模板和上下文合并,并輸出給用戶的途徑。Listing 5.2顯示了一個獨(dú)立應(yīng)用需要用到的相關(guān)代碼。

          import org.apache.velocity.app.Velocity;

          import org.apache.velocity.VelocityContext;

          import org.apache.velocity.Template;

          import org.apache.velocity.exception.ParseErrorException;

          import org.apache.velocity.exception.ResourceNotFoundException;

          import java.io.*;

          import java.util.ArrayList;

          public class Example {

          //從命令行參數(shù)獲取模板文件,并進(jìn)行初始化操作

          public Example(String templateFile) {

          try {

          Velocity.init();

          VelocityContext context = new VelocityContext();

          Template template = null;

          try {

          template = Velocity.getTemplate(templateFile);

          } catch(ResourceNotFoundException e2 ) {

          System.out.println(

          "cannot find template " + templateFile );

          } catch(ParseErrorException e ) {

          System.out.println(

          "Syntax error in template : " + e);

          }

          BufferedWriter writer = new BufferedWriter(

          new OutputStreamWriter(System.out));

          if ( template != null)

          template.merge(context, writer);

          writer.flush();

          writer.close();

          } catch( Exception e ) {

          System.out.println(e);

          }

          }

          public static void main(String[] args) {

          Example t = new Example(args[0]);

          }

          }

          Listing 5.2 The Velocity application without context. (continued)

          和許多的JAVA應(yīng)用程序一樣,這個示例需要導(dǎo)入一些JAVA包,前面5個導(dǎo)入了運(yùn)行Velocity需要的類。當(dāng)?shù)谝淮芜\(yùn)行這個示例時,需要在命令行提供模板文件名這個參數(shù)。如:

          java Example example.vm

          回頭查看Listing 5.2的模板示例我們可以看到,模板文件的名稱被放置到命令行上,并傳遞給新創(chuàng)建的示例對象。在這里,首先需要完成Velocity引擎的初始化操作,示例利用一個獨(dú)立模式關(guān)聯(lián)應(yīng)用程序和Velocity引擎,這就意味著僅有一個靜態(tài)引擎是可用的。記住這個事實(shí)很重要,因?yàn)槟憧隙ú幌M倏吹绞纠羞€有其他任何初始化引擎的代碼。

          一旦引擎被初始化,就將從本地磁盤上加載模板。模板是通過Velocity引擎對象的getTemplate(String)方法進(jìn)行加載的,該方法的結(jié)果是調(diào)用了一個模板對象;另外,如果沒有找到,就會拋出異常。很重要的一點(diǎn)是,當(dāng)找不到模板文件或把模板文件解析成模板對象出錯時,異常將通過ResourceNotFoundException進(jìn)行拋出。當(dāng)讀取模板并進(jìn)行解析時出錯,也會拋出ParseErrorException異常。

          當(dāng)模板被讀入到系統(tǒng)之后,你就可以開始處理輸出了。此處要注意的是,除了輸出到控制臺的方式外,還可以輸出為一個文件、一個套接字socket或其他的輸出。

          在這個示例里,你已經(jīng)在應(yīng)用程序里使用了幾個不同的內(nèi)容:

          Velocity一個靜態(tài)對象,表現(xiàn)為Velocity引擎

          Context一個上下文對象

          Template一個模板對象,在從本地磁盤讀入Velocity模板文件時創(chuàng)建

          Writer一個BufferedWriter對象,用于向控制臺直接輸出(通過System.out流)。在輸出前,要核實(shí)BufferedWriter已經(jīng)正確進(jìn)行了初始化。之后,Velocity引擎通過使用模板對象的merge()方法(帶有兩參數(shù):一個上下文對象和一個BufferedWriter對象)來完成內(nèi)容合并。merge()方法帶有兩參數(shù):一個上下文對象和一個BufferedWriter對象,當(dāng)模板對象執(zhí)行merge()方法時,上下文被合并到模板文件中,同時用上下文中對應(yīng)的值替換模板中的腳本元素,完成輸出創(chuàng)建工作。

          最后,沖洗(flush)和關(guān)閉輸出流。Figure 5.1 顯示了輸出結(jié)果。


          Figure 5.1
          Output from the Hello World example.

          在這個示例里,我們將Listing 5.1中的模板內(nèi)容保存為一個文件,命名為helloworld.vm。在這里,擴(kuò)展名不限于VM,也可以是其他的擴(kuò)展名,目的是與其他文件進(jìn)行區(qū)別,比如:HTMLJSP,當(dāng)然,也完全可以是定義的,比如XX。另外,我們把Listing 5.2的內(nèi)容保存到一個名叫Example.java的文件中,并將其編譯成class文件。

          javac Example.java

          執(zhí)行示例的命令為

          java Example helloworld.vm

          如果Velocity引擎不能定位模板文件位置,將產(chǎn)生一個錯誤。

          使用上下文的Velocity模板

          在上一個示例里,我們通過#set指令來給$name引用指定值。但這樣做將限制Velocity的動態(tài)處理能力,比如,如果需要動態(tài)的更改用戶名稱,就成為一個不可能完成的任務(wù)。要想獲得這個能力,需要使用上下文對象,在第二個示例里,我們使用和Listing 5.1相同的模板,但刪除了#set指令這一行,只保留現(xiàn)在這一行:

          Hello World, $name is Here

          JAVA代碼中找到下面這行代碼

          VelocityContext context = new VelocityContext();

          在其之后加上下面這行代碼:

          context.put("name", "New Sam");

          存儲這個文件,編譯和執(zhí)行它。你就將看到這樣的輸出“Hello World, New Sam is Here.”。現(xiàn)在讓我們試一試其他,打開這個應(yīng)用程序代碼,改變context.put的參數(shù)內(nèi)容。

          context.put("names", "New Sam");

          重新編輯并執(zhí)行。輸出結(jié)果為“Hello World, $name is here”,為什么會得到這個輸出?好,讓我們再仔細(xì)看一下context.put()語句。正如你在前面章節(jié)學(xué)到的一樣,Velocity像變魔法一樣把模板和上下文合并到一起,所有在模板的引用,比如$name必須和上下文對象中的關(guān)鍵字相匹配。因此,Velocity將嘗試在上下文對象中查找關(guān)鍵字“name”來與模板引用$name相匹配。如果匹配上了,則將上下文中關(guān)鍵字“name”中保存的值“New Sam”合并入模板并返回給用戶;如果在上下文中沒有找到對應(yīng)的關(guān)鍵字,引擎將直接把“$name”作為字符串返回,不進(jìn)行任何合并操作。

          在這里,之所有輸出為“Hello World, $name is here”,是因?yàn)槲覀儼?/span>context.put()的關(guān)鍵字改成了“names”,也就是說在上下文中保存的是“names”關(guān)鍵字的值,Velocity引擎也就不能匹配模板的$name引用,所以Velocity引擎直接返回$name字符串。

          使用WEBVelocity模板

          迄今為此,我們所做的兩個示例都是用于獨(dú)立的JAVA應(yīng)用程序。然而,當(dāng)把Velocity用于替代jSP時,你可能最期待的就是把Velocity用于WEB應(yīng)用程序。在這一節(jié)里,我們將看一看如何在Servlets里使用Velocity。關(guān)于這個主題的更多信息,詳見Chapter 12“在Servlets里使用Velocity”,Listing 5.3展示了一個用于在瀏覽器里顯示一個XML文檔的新模板。正如你所看到的一樣,這個模板有一些小的功能。

          在之后的章節(jié)里,我們將檢驗(yàn)更多的模板語句。目前,你首先需要關(guān)注的第一個在#foreach#next指令之間的語句。這些指令允許你創(chuàng)建一個基于某些引用(此處為$value)的循環(huán)。

          <?xml version="1.0" encoding="ISO-8859-1" ?>

          <list>

          #foreach( $value in $list )

          <number>$value</number>

          #end

          </list>

          Listing 5.3 The servlet example template.

          Listing 5.4 向你展示了用于產(chǎn)生XMLservlet代碼。正如我們說及的一樣,我們將在Chapter 12詳細(xì)討論Servlets,這里我們只關(guān)注Velocity對象的創(chuàng)建和三個增加到里面的值。用context.put("list", v)語句把整個Vector對象附屬到上下文中。

          import java.util.Vector;

          import javax.servlet.http.HttpServletRequest;

          import javax.servlet.http.HttpServletResponse;

          import org.apache.velocity.Template;

          import org.apache.velocity.context.Context;

          import org.apache.velocity.servlet.VelocityServlet;

          import org.apache.velocity.exception.ResourceNotFoundException;

          import org.apache.velocity.exception.ParseErrorException;

          public class VelocityServletExample extends VelocityServlet {

          public Template handleRequest( HttpServletRequest request,

          HttpServletResponse response,

          Context context ) {

          Vector v = new Vector();

          v.add("one");

          v.add("two");

          v.add("three");

          context.put("list", v);

          Template template = null;

          try {

          template = getTemplate("displaylist.vm");

          } catch( Exception e ) {

          System.out.println("Error " + e);

          }

          return template;

          }

          }

          Listing 5.4 The servlet code for our example.

          一旦vector被放置到上下文對象中,就需要從本地磁盤上獲取用于顯示上下文信息的模板。現(xiàn)在不再使用模板對象的merge()方法進(jìn)行合并操作,而是簡單的返回模板。這個模板實(shí)際上不會直接返回給用戶,而是在后臺對“被返回來的”模板和上下文進(jìn)行合并處理,并返回給用戶一個XML的類型的內(nèi)容。在Figure 5.2里,你可以看到由Servlets和模板創(chuàng)建的XML輸出。如果需要,你也可以使用Velocity向用戶的瀏覽器輸出HTML


          Figure 5.2
          The servlet and template example output.

          本章小節(jié)和下章介紹

          在這一章里,我們向你展示了如何用Velocity來書寫Hello World獨(dú)立應(yīng)用程序。你可以使用Velocity來開發(fā)獨(dú)立應(yīng)用程序和WEB應(yīng)用。在下一章里,我們將開始詳細(xì)介紹Velocity,并學(xué)習(xí)它與其他語言不一樣的特性。

          posted on 2008-10-13 00:42 KINGWEE 閱讀(726) 評論(0)  編輯  收藏 所屬分類: Velocity

          主站蜘蛛池模板: 子长县| 南陵县| 商洛市| 鄂托克前旗| 太湖县| 留坝县| 龙岩市| 泾川县| 于田县| 杭州市| 平潭县| 长汀县| 桐柏县| 麻城市| 淮滨县| 贞丰县| 弥勒县| 那坡县| 德清县| 东光县| 宜川县| 威信县| 钟山县| 锦州市| 绥德县| 青岛市| 镇安县| 石狮市| 涿州市| 商水县| 库车县| 滨州市| 元朗区| 孝昌县| 时尚| 东城区| 文成县| 邛崃市| 从江县| 鲜城| 三河市|