五步輕鬆替代JSP Struts與Velocity集成

 Java™ 服務器頁面(JSP)技術是如此普及,以至於人們忘記了在創建 Web 頁面時還有其他選擇。但是最近,有些開發人員已經轉向模板引擎,以獲得在 JSP 中得不到的靈活性。雖然用 JSP 和模板引擎都可以把數據嵌入 HTML,但是每種技術都有自己的處理方式。Velocity 模板是一個特別流行的 JSP 替代品。Velocity 提供了平緩的學習曲線和巨大的易用性。開發人員喜歡它簡潔的語法,而且性能分析也證明它的性能超出 JSP。Velocity 也非常容易集成進 Struts 應用程序。

       在這篇文章中,我將介紹如何在 Struts 應用程序中集成和使用 Velocity 模板引擎。我會首先提供一個公式,然後逐步展開它。生成的應用程序組合了 Struts 和 Velocity —— 一個第一流的組合,可能會讓您懷疑自己對 JSP 的忠誠!

      關於模板引擎

      在開始集成 Struts 和 Velocity 的簡單任務之前,讓我們先確保您理解模板引擎和它們在視圖生成中的角色。模板引擎作爲整體概念,Velocity 作爲具體實現,它們的生命在 HTML 之外。Velocity 把數據合併到文本主體中不同的點上。文本可以是文字、電子郵件或 HTML。由於採用這種方式,Velocity 模板引擎有點兒像 Microsoft Word 的“郵件合併”特性。郵件合併允許您方便地把動態數據(例如姓名、地址和電話號碼)合併到信件中。在早期的日子裏,組織用這項特性生成大型郵件列表並把它們送到郵局,導致垃圾郵件的產生!

      在 Web 應用程序中,Velocity 實現的目標與 JSP 相同:可以用它在向 HttpServletResponse 的 OutputStream 發送之前生成要發送的 HTML。在 Struts 應用程序中使用 Velocity 的一種方式是在 Struts 的 Action 內部寫入響應,然後返回 null 的 ActionForward。雖然這種技術可行,但卻有嚴重的缺陷:無法使用 struts-config.xml 文件把響應抽象出來。把視圖放在 Action 內部,意味着如果想要修改響應,就必須修改 Action。

      因爲這種技術剝奪了 Struts 最好的一項特性(即從視圖中抽象出重點的能力),所以我更願意把所有響應指向一個 servlet,由它負責訪問 Velocity 模板,合併上下文的數據,生成響應,然後再送回瀏覽器。稍後就會學到,Velocity 的設計者們已經把這些步驟全都捆綁在了一起:您需要做的只是跟着我來看如何一步步地實現它們。

      Velocity 是一個基於 Java 的模板引擎,它提供了簡單的基於模板的語言,可以用類似腳本的方式引用對象。Velocity 促進了分離團隊成員之間的責任:允許 Web 設計人員專注於視圖(即頁面的觀感),而 Java 程序員專注於後端代碼。把 Java 代碼從頁面佈局中分離出來,會讓 Web 應用程序未來更易維護。當 Velocity 與 Sruts 這樣的 MVC 框架結合時,就成了 JSP 或 PHP 可行的替代。)

      Velocity 的五步

      把 Struts 與 Velocity 模板引擎組合起來很簡單,也很直接;實際上,只要用五步就可以實現:

1. 把 Velocity JAR 放在類路徑中。
2. 修改 web.xml 文件讓它識別 Velocity servlet。
3. 把 Velocity toolbox.xml 放在應用程序的 WEB-INF 目錄下。
4. 修改 struts-config,把它的視圖指向 Velocity 模板而不是 JSP。
5. 爲每個需要顯示的頁面創建 Velocity 模板。

      我將用一個熟悉的搜索用例來演示 Struts 與 Velocity 的集成。在這個示例中,一個簡單的應用程序允許用戶按照圖書的 ISBN 編號搜索圖書。應用程序的結果頁面顯示與 ISBN 編號匹配的圖書。

      第 1 步:把 Velocity JAR 放在 WEB-INF/lib 下

      如果您還沒下載 Velocity,那麼現在需要下載它。Velocity 本身是很棒的,但是它的工具包可以幫助您把工作做得更好更快。特別是 Struts 工具模擬了您以前熟悉的 Struts 標記。

      請注意不同時候,需要的 jar 也會略有不同。在這裏我不想列出一個 JAR 列表,只是想建議您訪問 Velocity 的主頁並閱讀那裏的安裝指南。一旦得到了需要的 JAR,只需把它們放在 WEB-INF/lib 下面即可。

       第 2 步:修改 web.xml,讓它識別 Velocity 的 servlet

       下一步是修改 Struts 的 web.xml 文件,讓它識別 Velocity 的 servlet 並把所有以 .vm 結尾的資源請求定向到 Velocity servlet,如清單 1 所示。

清單 1. 修改 web.xml,聲明 Velocity servlet

<servlet>
  <servlet-name>velocity</servlet-name> |(1)
  <servlet-class> |(2)
         org.apache.velocity.tools.view.servlet.VelocityViewServlet
  </servlet-class>                                           

  <init-param> |(3)
    <param-name>org.apache.velocity.toolbox</param-name>
    <param-value>/WEB-INF/toolbox.xml</param-value>     
 </init-param>                                                

 <load-on-startup>10</load-on-startup> |(4)
</servlet>

<!-- Map *.vm files to Velocity -->
<servlet-mapping> |(5)
  <servlet-name>velocity</servlet-name>
  <url-pattern>*.vm</url-pattern>     
</servlet-mapping>

      讓我們來看看清單 1 中發生了什麼:

• (1)聲明瞭 Velocity servlet 並給了它一個 velocity 句柄。
• (2)聲明瞭 Velocity servlet 的類名。
Velocity servlet 接受“toolbox”參數。toolbox 是聲明應用程序的可用工具的位置。因此,在清單 1 中,我還做了以下工作:
• (3)告訴 VelocityServlet 在哪裏可以找到 toolbox 的配置。
• (4)設置了 load-on-startup 標記,確保在正確的時間裝入 Velocity servlet。任何大於或等於 0 的值都會迫使容器通過調用 servlet 的 init() 方法來裝入它。放在 load-on-startup 標記體中的值決定了不同的 servlet 的 init 方法調用的次序。例如,0 在 1 之前調用,而 1 在 2 之前調用。缺少的標記或負值允許 servlet 容器根據自己的選擇裝入 servlet。
• (5)聲明瞭 servlet 映射,強迫所有用 .vm 結尾的資源請求定向到 Velocity servlet。請注意(5)中的<servlet-name> 必須與(1)中的<servlet-name> 匹配。交錯的聲明和映射會在日誌中生成錯誤。

      第 3 步:把 toolbox.xml 放在 WEB-INF 下

      利用 Velocity,可以使用(或創建)包含許多工具的工具箱。用來登記類的工具箱中包含有用的函數,常常會用到。幸運的是,Velocity 提供了許多預先構建好的工具。還創建了許多 Struts 工具來模擬原始的 Struts 標記。如果發現需要構建自己的工具,也可以自由地構建。在清單 2 中顯示的 toolbox.xml 可以在 Velocity 工具下載中找到。這個文件應當隨 Velocity JAR 一起放在 WEB-INF 下。

清單 2. toolbox.xml

<?xml version="1.0"?>
<toolbox>
  <tool>
     <key>link</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.StrutsLinkTool
     </class>
  </tool>
  <tool>
     <key>msg</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.MessageTool
     </class>
  </tool>
  <tool>
     <key>errors</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.ErrorsTool
     </class>
  </tool>
  <tool>
     <key>form</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.FormTool
     </class>
  </tool>
  <tool>
     <key>tiles</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.TilesTool
     </class>
  </tool>
  <tool>
     <key>validator</key>
     <scope>request</scope>
     <class>
       org.apache.velocity.tools.struts.ValidatorTool
     </class>
  </tool>
</toolbox>

      第 4 步:修改 struts-config

      下一步是修改 struts-config.xml,指向 Velocity 視圖而不是 JSP。新的配置文件如清單 3 所示。

清單 3. 針對 Velocity 視圖修改後的 struts-config.xml

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

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">

<struts-config>
    <form-beans>
        <form-bean name="searchForm" type="app.SearchForm"/>
    </form-beans>

    <global-forwards>
        <forward name="welcome" path="/welcome.do"/>
    </global-forwards>
 
   <action-mappings>
        <action
            path="/welcome"
            type="org.apache.struts.actions.ForwardAction"
            parameter="/pages/search.vm"/> |(1)

        <action
            path="/search"
            type="app.SearchAction"
            name="searchForm"   
            scope="request"
            input="/pages/search.vm"> |(2)
            <forward name="success"
              path="/pages/results.vm"/> |(3)
        </action>
    </action-mappings>
</struts-config>

      清單 3 看起來就像一個非常典型的 Struts 應用程序,只有一個小小的不同。響應沒有把客戶轉向到 JSP,而直接轉向到 .vm 文件(請參閱清單 3 中的引用 1、2 和 3)。在大多數情況下,把 Struts 應用程序從 JSP 遷移到 Velocity 視圖,需要做的僅僅是全局搜索,把 .jsp 替換成 .vm。其他所有東西都可以保持不變!模板可以同樣保存在以前保存 JSP 的位置;所需要做的只是用 Velocity 命令代替 JSP 標記。

      第 5 步:創建 Velocity 模板

      在清單 4 中,可以看到示例應用程序搜索頁面的 Velocity 模板。

清單 4. 搜索頁面的 Velocity 模板

<HTML>
  <HEAD>
    <TITLE>Search</TITLE>
  </HEAD>
  <BODY>
    $!errors.msgs()||(1)
    <FORM method="POST"
      action="$link.setAction('/search')"> |(2)
      <h2>Book Search</h2>
      ISBN:<INPUT type="text" name="isbn">
      <INPUT type="submit" value="Submit" name="submit">
    </FORM>
  </BODY>
</HTML>

       清單 4 是一個沒有 JSP 或 Struts 標記的典型的 HTML 頁面。但是,以下元素看起來可能不是那麼熟悉:

• (1)用 $!errors.msgs() 得到錯誤消息隊列中的錯誤消息。
• (2)用 $link.setAction('/search') 獲得搜索轉發的 URL。

       這就成功了 —— 模板剩下的部分看起來幾乎與以前熟悉的 HTML 文件相同。清單 5 顯示了應用程序結果頁面的模板。

清單 5. 結果頁面的 Velocity 模板

<html>
  <body>

  <h1>Book Details</h1>
  <a href="$link.setForward("searchEntry")">Search again</a> |(1)

  <h3>$book.title</h3> |(2)

    <b>ISBN:</b>$book.isbn<br>|(3)
    <b>Title:</b>$book.title<br>|(4)
    <b>Author:</b>$book.author<br>|(5)
    <b>Price:</b>$book.price<br>|(6)
    <b>No Pages:</b>$book.pages<br>|(7)
    <b>Description:</b>$book.description<br>|(8)
    <b>Publisher:</b>$book.publisher<br>|(9)
  </body>
<html>

      可以注意到,清單 5 中不包含 JSP 標記或 Struts 標記。我們來詳細看看它:

• (1)用 Struts 的鏈接工具把 <a> 標記的 href 設置爲 Struts 轉發。
• (2)訪問 $book title 屬性。
• (3)訪問 $book isbn 屬性。
• (4)再次訪問 $book title 屬性。
• (5)訪問 $book author 屬性。
• (6)訪問 $book price 屬性。
• (7)訪問 $book pages 屬性。
• (8)訪問 $book description 屬性。
• (9)訪問 $book publisher 屬性。

      討論

      就是把 Struts 與 Velocity 模板引擎集成的全部工作。表面看起來非常簡單(實際上也很簡單),但是請想想是什麼讓這個集成能夠工作的呢?
Struts 動作映射可以定義任何視圖,不僅限於 JSP。在這篇文章中,我只是把動作映射修改爲以 vm 結尾而不是以 jsp 結尾的返回文件。然後,我聲明瞭 Velocity servlet,並告訴 Servlet 容器把以 vm 結尾的文件發送給 VelocityViewServlet。
VelocityViewServlet 把 Velocity 命令表示成 HTML 響應。通過這種方式,VelocityViewServlet 充當了視圖響應的攔截器。Struts 控制器把視圖轉發給 VelocityViewServlet,後者在向客戶端發送響應之前處理 vm 文件。請參閱 參考資料 獲得關於將 Velocity 視圖集成進 Struts 應用程序的更多內容。

      結束語

      正如在本文中看到的,Struts 與 Velocity 的集成很簡單。只需五個步驟就可以把所有東西連在一起。針對不同的引擎和場景,採用模板引擎而不是 JSP 的優勢各有不同。在 Velocity 的情況下,優勢就是簡單性、容易學習以及更好的性能。

• (1)用 $!errors.msgs() 得到錯誤消息隊列中的錯誤消息。
• (2)用 $link.setAction('/search') 獲得搜索轉發的 URL。

       這就成功了 —— 模板剩下的部分看起來幾乎與以前熟悉的 HTML 文件相同。清單 5 顯示了應用程序結果頁面的模板。

清單 5. 結果頁面的 Velocity 模板

<html>
  <body>

  <h1>Book Details</h1>
  <a href="$link.setForward("searchEntry")">Search again</a> |(1)

  <h3>$book.title</h3> |(2)

    <b>ISBN:</b>$book.isbn<br>|(3)
    <b>Title:</b>$book.title<br>|(4)
    <b>Author:</b>$book.author<br>|(5)
    <b>Price:</b>$book.price<br>|(6)
    <b>No Pages:</b>$book.pages<br>|(7)
    <b>Description:</b>$book.description<br>|(8)
    <b>Publisher:</b>$book.publisher<br>|(9)
  </body>
<html>

      可以注意到,清單 5 中不包含 JSP 標記或 Struts 標記。我們來詳細看看它:

• (1)用 Struts 的鏈接工具把 <a> 標記的 href 設置爲 Struts 轉發。
• (2)訪問 $book title 屬性。
• (3)訪問 $book isbn 屬性。
• (4)再次訪問 $book title 屬性。
• (5)訪問 $book author 屬性。
• (6)訪問 $book price 屬性。
• (7)訪問 $book pages 屬性。
• (8)訪問 $book description 屬性。
• (9)訪問 $book publisher 屬性。

      討論

      就是把 Struts 與 Velocity 模板引擎集成的全部工作。表面看起來非常簡單(實際上也很簡單),但是請想想是什麼讓這個集成能夠工作的呢?
Struts 動作映射可以定義任何視圖,不僅限於 JSP。在這篇文章中,我只是把動作映射修改爲以 vm 結尾而不是以 jsp 結尾的返回文件。然後,我聲明瞭 Velocity servlet,並告訴 Servlet 容器把以 vm 結尾的文件發送給 VelocityViewServlet。
VelocityViewServlet 把 Velocity 命令表示成 HTML 響應。通過這種方式,VelocityViewServlet 充當了視圖響應的攔截器。Struts 控制器把視圖轉發給 VelocityViewServlet,後者在向客戶端發送響應之前處理 vm 文件。請參閱 參考資料 獲得關於將 Velocity 視圖集成進 Struts 應用程序的更多內容。

      結束語

      正如在本文中看到的,Struts 與 Velocity 的集成很簡單。只需五個步驟就可以把所有東西連在一起。針對不同的引擎和場景,採用模板引擎而不是 JSP 的優勢各有不同。在 Velocity 的情況下,優勢就是簡單性、容易學習以及更好的性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章