Velocity空間

          快速構建JAVA應用
          隨筆 - 11, 文章 - 15, 評論 - 5, 引用 - 0
          數據加載中……

          CHAPTER 5 構建Hello World示例

           

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

          Hello World!

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

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

          不使用上下文的Velocity模板

          使用上下文的Velocity模板

          使用WEBVelocity模板

          如果你已經非常熟悉服務器端語言,比如PHP,你或許會非常驚奇,在Velocity模板被瀏覽時,我們為什么不討論WEB服務器的解釋程序。這是因為Velocity并不含解釋程序,它是純JAVA語言,屬性編譯運行方式,而非解釋運行方式。所有在模板和上下文之間的合并處理都是通過JAVA代碼來完成的。這些JAVA代碼可能存在于Servlet中,也可嵌入JSP或應用程序中。

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

          不使用上下文的Velocity模板

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

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

          #set( $name = "Sam" )

          Hello World, $name is Here

          Listing 5.1 The Velocity Hello World template.

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

          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 {

          //從命令行參數獲取模板文件,并進行初始化操作

          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應用程序一樣,這個示例需要導入一些JAVA包,前面5個導入了運行Velocity需要的類。當第一次運行這個示例時,需要在命令行提供模板文件名這個參數。如:

          java Example example.vm

          回頭查看Listing 5.2的模板示例我們可以看到,模板文件的名稱被放置到命令行上,并傳遞給新創建的示例對象。在這里,首先需要完成Velocity引擎的初始化操作,示例利用一個獨立模式關聯應用程序和Velocity引擎,這就意味著僅有一個靜態引擎是可用的。記住這個事實很重要,因為你肯定不希望再看到示例中還有其他任何初始化引擎的代碼。

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

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

          在這個示例里,你已經在應用程序里使用了幾個不同的內容:

          Velocity一個靜態對象,表現為Velocity引擎

          Context一個上下文對象

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

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

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


          Figure 5.1
          Output from the Hello World example.

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

          javac Example.java

          執行示例的命令為

          java Example helloworld.vm

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

          使用上下文的Velocity模板

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

          Hello World, $name is Here

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

          VelocityContext context = new VelocityContext();

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

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

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

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

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

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

          使用WEBVelocity模板

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

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

          <?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 向你展示了用于產生XMLservlet代碼。正如我們說及的一樣,我們將在Chapter 12詳細討論Servlets,這里我們只關注Velocity對象的創建和三個增加到里面的值。用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被放置到上下文對象中,就需要從本地磁盤上獲取用于顯示上下文信息的模板。現在不再使用模板對象的merge()方法進行合并操作,而是簡單的返回模板。這個模板實際上不會直接返回給用戶,而是在后臺對“被返回來的”模板和上下文進行合并處理,并返回給用戶一個XML的類型的內容。在Figure 5.2里,你可以看到由Servlets和模板創建的XML輸出。如果需要,你也可以使用Velocity向用戶的瀏覽器輸出HTML


          Figure 5.2
          The servlet and template example output.

          本章小節和下章介紹

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

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

          主站蜘蛛池模板: 西和县| 万安县| 邻水| 宜阳县| 柳江县| 福建省| 桃源县| 玉树县| 德清县| 乌海市| 拉萨市| 右玉县| 永和县| 金寨县| 柘荣县| 九寨沟县| 深泽县| 榕江县| 钟山县| 高阳县| 大同县| 都安| 仲巴县| 衡南县| 景宁| 双桥区| 修武县| 惠安县| 龙泉市| 文昌市| 尚志市| 那曲县| 洮南市| 盐池县| 手游| 县级市| 库伦旗| 宜春市| 鱼台县| 米泉市| 逊克县|