茫茫網海中的冷日 - 對這文章發表回應
茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1729061 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
F09_525.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

對這文章發表回應

發表限制: 非會員 可以發表

發表者: 冷日 發表時間: 2008/3/18 4:27:56
本文介紹 Struts,它是使用 servlet 和 JavaServer Pages技術的一種 Model-View-Controller 實現。Struts 可幫助您控制 Web項目中的變化並提高專業化水平。儘管您可能永遠不會用 Struts實現一個系統,但您可以將其中的一些思想用於您以後的 servlet 和 JSP網頁的實現中。

簡介
小學生也可以在因特網上發布 HTML網頁。但是,小學生的網頁和專業開發的網站有質的區別。網頁設計人員(或者HTML開發人員)必須理解顏色、用戶、生產流程、網頁布局、瀏覽器兼容性、圖像創建和JavaScript 等等。設計漂亮的網站需要做大量的工作,大多數 Java開發人員更注重創建優美的對象接口,而不是用戶界面。JavaServer Pages(JSP) 技術為網頁設計人員和 Java 開發人員提供了一種聯繫鈕帶。

如果您開發過大型 Web應用程序,您就理解 變化 這個詞的含義。「模型-視圖-控制器」(MVC)就是用來幫助您控制變化的一種設計模式。MVC減弱了業務邏輯接口和數據接口之間的耦合。Struts 是一種 MVC實現,它將 Servlet 2.2 和 JSP 1.1 標記(屬於 J2EE規範)用作實現的一部分。儘管您可能永遠不會用 Struts實現一個系統,但了解一下 Struts或許使您能將其中的一些思想用於您以後的 Servlet 的 JSP 實現中。

在本文中,我將以一個 JSP文件為起點討論該網頁的優缺點,該文件中使用的元素可能是您所熟悉的。隨後我將討論Struts,並說明它是如何控制您的 Web項目中的變化並提高專業化水平的。最後,我將重新開發這個簡單的 JSP文件,在開發過程中我已顧及到網頁設計人員和變化。

一個 JSP 文件就是一個 Java servlet

JavaServer Page (JSP) 文件只是審視 servlet 的另一種方式。JSP文件的概念使我們能夠將 Java servlet 看作一個 HTML 網頁。JSP 消除了Java 代碼中經常出現的討厭的 print() 語句。JSP文件首先被預處理為 .java 文件,然後再編譯為.class 文件。如果您使用的是 Tomcat,則可以在work 目錄下查看預處理後的 .java文件。別的容器可能將 .java 和 .class文件存儲在其他位置;這個位置與容器有關。圖 1 說明了從 JSP 文件到servlet 的流程。

圖 1. 從 JSP 文件到 servlet的流程
從 JSP 到 servlet 的流程

(這與 Microsoft 的 Active Server Page (ASP) 明顯不同。ASP被編譯到內存中,而不是編譯到一個單獨的文件中。)

簡單的獨立 JSP 文件
在小型 JSP應用程序中,經常會看到數據、業務邏輯和用戶界面被組合在一個代碼模塊中。此外,應用程序通常還包含用來控制應用程序流程的邏輯。清單1 和圖 2 展示了允許用戶加入一個郵件列表的一個簡單 JSP 文件。

清單 1. join.jsp -- 一個簡單的請求和響應 JSP文件

<%@ page language="java" %>
  <%@ page import="business.util.Validation" %>
    <%@ page import="business.db.MailingList" %>
      <% String error = ""; String email = request.getParameter("email"); // 是否有電子郵件地�} 
        if( email!=null ) { // 驗證輸入... 
        if( business.util.Validation.isValidEmail(email) ) { // 存儲輸入... 
        try { business.db.MailingList.AddEmail(email); } 
        catch (Exception e) 
        { error = "Error adding email address to system." + e; } 
        if( error.length()==0 ) { %> // 重定向到歡迎頁...
        <jsp:forward page="welcome.html"/>
        <% 
        } 
        } else { // �]置錯誤消息並重新顯示網頁 
        error = email + " is not a valid email address, please try again."; } } 
        else { email = ""; } %>
          <html>
            <head>
              <title>
                Join Mailing List
              </title>
            </head>
            <body>
              <font color=red>
                <%=error%>
              </font>
              <br>
              <h3>Enter your email to join the group</h3>
              <form action="join.jsp" name="joinForm">
                <input name="email" id="email" value=<%=email%>
                >
                </input>
                <input type=submit value="submit">
              </form>
            </body>
          </html> 

圖 2. 在簡單的請求和響應中,JSP文件設置數據、控制到下一個網頁的流程並創建 HTML
簡單的請求和響應 JSP

這個郵件列表 JSP文件是一個獨立的、自主完成所有任務的模塊。未包含在這個 JSP文件中的僅有代碼是包含在 isValidEmail()中的實際驗證代碼和將電子郵件地址存入數據庫的代碼。(將isValidEmail()方法分離到可重用的代碼中似乎是當然的選擇,但我曾見過直接嵌入網頁中的isValidEmail()代碼。單頁方法的優點是易於理解,並且最初也易於構建。此外,對於各種圖形化開發工具,入門也很容易。

join.jsp 的活動

  1. 顯示打開的輸入網頁。
  2. 從表單參數中讀取 email 的值。
  3. 驗證 email 地址。
  4. 如果 email 地址有效:
    • 將該地址添加到數據庫中。
    • 重定向到下一個網頁。
  5. 如果 email 地址無效:
    • 設置錯誤消息。
    • 重新顯示含有錯誤消息的 join.jsp。

單頁方法的後果

  • HTML 和 Java 強耦合在一起
    JSP 文件的編寫者必須既是網頁設計者,又是 Java開發者。其結果通常要麼是很糟的 Java代碼,要麼是難看的網頁,有時甚至 Java 代碼和網頁都很糟。

  • Java 和 JavaScript 的不足
    隨著網頁逐漸變大,很容易想到實現一些 JavaScript。當網頁中出現JavaScript 時,這種腳本就可能與 Java代碼產生混淆。可能產生混淆的一個例子是使用客戶端的 JavaScript來驗證 email 域。


  • 內嵌的流程邏輯
    要理解應用程序的整個流程,您必須瀏覽所有網頁。試想一下擁有 100個網頁的網站的錯綜複雜的邏輯。

  • 調試困難
    除了很糟的外觀之外,HTML 標記、Java 代碼和 JavaScript代碼都集中在一個網頁中還使調試變得相當困難。

  • 強耦合
    更改業務邏輯或數據可能牽涉相關的每個網頁。

  • 美學
    在很大的網頁中,這編碼樣式看起來雜亂無章。我過去進行 Microsoft ASP開發時,我經常看到有 1000行的網頁。即使有彩色語法顯示,閱讀和理解這些代碼仍然比較困難。

請別在我的 HTML 中加入太多的 Java代碼
在清單 1 中,不是 Java 代碼中有大量的 HTML,而是在 HTML文件中有大量的 Java 代碼。從這個觀點來看,除了允許網頁設計人員編寫Java 代碼之外,我實際上沒做什麼。但是,我們並不是一無所有;在 JSP1.1 中,我們獲得一種稱為「標記」的新特性。

JSP 標記只是將代碼從 JSP 文件中抽取出來的一種方式。有人將 JSP標記看作是 JSP 文件的宏,其中用於這個標記的代碼包含在 servlet中。(宏的觀點在很大程度上是正確的。)出於同樣的原因,我不希望在Java 代碼中看到 HTML 標記,我也不希望在 JSP 文件中看到 Java代碼。JSP 技術的整個出發點就是允許網頁設計人員創建servlet,而不必糾纏於 Java 代碼。標記允許 Java 程序員將 Java代碼偽裝成 HTML 來擴展 JSP 文件。圖 3 顯示了從 JSP網頁中抽取代碼並將它們放入 JSP 標記中的一般概念。

圖 3. JSP 標記

JSP 標記分解

清單 2 是用來說明 Struts 標記的功能的一個例子。在清單 2中,正常的 HTML<form> 標記被用 Struts<form:form> 標記替換。清單 3顯示了瀏覽器接收到的結果 HTML。瀏覽器獲得 HTML<form> 標記,但帶有附加代碼,如JavaScript。附加的 JavaScript 激活 email地址域。服務器端的<form:form> 標記代碼創建適當的 HTML,並使網頁設計人員不再接觸 JavaScript。

清單 2. Struts 的 form 標記

          <form:form action="join.do" focus="email" >
            <form:text property="email" size="30" maxlength="30"/>
            <form:submit property="submit" value="Submit"/>
            </form:form> 


清單 3. 發送給瀏覽器的結果 HTML


            <form name="joinForm" method="POST" action="join.do;jsessionid=ndj71hjo01">
              <input type="text" name="email" maxlength="30" size="30" value="">
              <input type="submit" name="submit" value="Submit">
            </form>
<script language="JavaScript">
<!--
document.joinForm.email.focus()
// -->
</script> 

有關 JSP 標記的注意事項:

  • JSP 標記需要一個運行 JSP 1.1 或更高版本的容器。

  • JSP 標記在服務器上運行,而不像 HTML標記那樣由客戶機解釋。

  • JSP 標記提供了適當的代碼重用機制。

  • 可以使用一種稱為 include 的 JSP 機制將 HTML 和JavaScript 添加到網頁中。但是,開發人員常常會創建巨大的 JavaScript庫文件,這些庫文件被包含在 JSP 文件中。結果返回給客戶機的 HTML網頁要比必需的 HMTL 網頁大得多。include的正確用法是僅將它用於生成諸如頁眉和頁腳這類內容的 HTML代碼段。

  • 通過抽取出 Java 代碼,JSP 標記使開發角色更加專業化。

模型-視圖-控制器 (MVC)
JSP標記只解決了部分問題。我們還得處理驗證、流程控制和更新應用程序的狀態等問題。這正是MVC 發揮作用的地方。MVC通過將問題分為三個類別來幫助解決單一模塊方法所遇到的某些問題:

  • Model(模型)
    模型包含應用程序的核心功能。模型封裝了應用程序的狀態。有時它包含的唯一功能就是狀態。它對視圖或控制器一無所知。

  • View(視圖)
    視圖提供模型的表示。它是應用程序的 外觀 。視圖可以訪問模型的讀方法,但不能訪問寫方法。此外,它對控制器一無所知。當更改模型時,視圖應得到通知。

  • Controller(控制器)
    控制器對用戶的輸入作出反應。它創建並設置模型。

MVC Model 2

Web向軟件開發人員提出了一些特有的挑戰,最明顯的就是客戶機和服務器的無狀態連接。這種無狀態行為使得模型很難將更改通知視圖。在Web上,為了發現對應用程序狀態的修改,瀏覽器必須重新查詢服務器。

另一個重大變化是實現視圖所用的技術與實現模型或控制器的技術不同。當然,我們可以使用Java(或者 PERL、C/C++ 或別的語言)代碼生成HTML。這種方法有幾個缺點:

  • Java 程序員應該開發服務,而不是 HTML。
  • 更改布局時需要更改代碼。
  • 服務的用戶應該能夠創建網頁來滿足它們的特定需要。
  • 網頁設計人員不能直接參與網頁開發。
  • 嵌在代碼中的 HTML 很難看。

對於 Web,需要修改標準的 MVC 形式。圖 4 顯示了 MVC 的 Web改寫版,通常也稱為 MVC Model 2 或 MVC 2。

圖 4. MVC Model2
MVC Model 2

Struts,MVC 2 的一種實現
Struts 是一組相互協作的類、servlet 和 JSP標記,它們組成一個可重用的 MVC 2 設計。這個定義表示 Struts是一個框架,而不是一個庫,但 Struts也包含了豐富的標記庫和獨立於該框架工作的實用程序類。圖 5 顯示了Struts 的一個概覽。

圖 5. Struts概覽

Struts 概覽

Struts 概覽

  • Client browser(客戶瀏覽器)
    來自客戶瀏覽器的每個 HTTP 請求創建一個事件。Web 容器將用一個 HTTP響應作出響應。

  • Controller(控制器)
    控制器接收來自瀏覽器的請求,並決定將這個請求發往何處。就 Struts而言,控制器是以 servlet實現的一個命令設計模式。struts-config.xml文件配置控制器。

  • 業務邏輯
    業務邏輯更新模型的狀態,並幫助控制應用程序的流程。就 Struts而言,這是通過作為實際業務邏輯「瘦」包裝的 Action類完成的。

  • Model(模型)的狀態
    模型表示應用程序的狀態。業務對象更新應用程序的狀態。ActionForm bean在會話級或請求級表示模型的狀態,而不是在持久級。JSP 文件使用 JSP標記讀取來自 ActionForm bean 的信息。

  • View(視圖)
    視圖就是一個 JSP文件。其中沒有流程邏輯,沒有業務邏輯,也沒有模型信息 --只有標記。標記是使 Struts 有別於其他框架(如Velocity)的因素之一。

詳細分析 Struts
圖 6 顯示的是 org.apache.struts.action 包的一個最簡UML 圖。圖 6 顯示了 ActionServlet(Controller)、ActionForm (Form State) 和Action (Model Wrapper) 之間的最簡關係。


圖 6. Command (ActionServlet)與 Model (Action & ActionForm) 之間的關係的 UML圖
ActionServlet 與 Action 和 ActionForm 的關係

ActionServlet 類
您還記得函數映射的日子嗎?在那時,您會將某些輸入事件映射到一個函數指針上。如果您對此比較熟悉,您會將配置信息放入一個文件,並在運行時加載這個文件。函數指針數組曾經是用C 語言進行結構化編程的很好方法。

現在好多了,我們有了 Java 技術、XML、J2EE,等等。Struts的控制器是將事件(事件通常是 HTTP post)映射到類的一個servlet。正如您所料 --控制器使用配置文件以使您不必對這些值進行硬編碼。時代變了,但方法依舊。

ActionServlet 是該 MVC 實現的 Command部分,它是這一框架的核心。ActionServlet (Command)創建並使用 Action、ActionForm 和ActionForward。如前所述,struts-config.xml文件配置該 Command。在創建 Web 項目時,您將擴展 Action和 ActionForm 來解決特定的問題。文件struts-config.xml 指示 ActionServlet如何使用這些擴展的類。這種方法有幾個優點:

  • 應用程序的整個邏輯流程都存儲在一個分層的文本文件中。這使得人們更容易查看和理解它,尤其是對於大型應用程序而言。

  • 網頁設計人員不必費力地閱讀 Java代碼來理解應用程序的流程。

  • Java 開發人員也不必在更改流程以後重新編譯代碼。

可以通過擴展 ActionServlet 來添加 Command功能。

ActionForm 類


ActionForm 維護 Web應用程序的會話狀態。ActionForm是一個抽象類,必須為每個輸入表單模型創建該類的子類。當我說 輸入表單模型 時,是指ActionForm 表示的是由 HTML表單設置或更新的一般意義上的數據。例如,您可能有一個由 HTML表單設置的 UserActionForm。Struts框架將執行以下操作:

  • 檢查 UserActionForm是否存在;如果不存在,它將創建該類的一個實例。

  • Struts 將使用 HttpServletRequest 中相應的域設置UserActionForm 的狀態。沒有太多討厭的request.getParameter() 調用。例如,Struts框架將從請求流中提取 fname,並調用UserActionForm.setFname()。

  • Struts 框架在將 UserActionForm 傳遞給業務包裝UserAction 之前將更新它的狀態。

  • 在將它傳遞給 Action 類之前,Struts 還會對UserActionForm 調用 validation()方法進行表單狀態驗證。 註: 這並不總是明智之舉。別的網頁或業務可能使用UserActionForm,在這些地方,驗證可能有所不同。在UserAction 類中進行狀態驗證可能更好。

  • 可在會話級維護 UserActionForm。

註:

  • struts-config.xml 文件控制 HTML 表單請求與ActionForm 之間的映射關係。
  • 可將多個請求映射到 UserActionForm。
  • UserActionForm可跨多頁進行映射,以執行諸如嚮導之類的操作。

Action 類
Action 類是業務邏輯的一個包裝。Action類的用途是將 HttpServletRequest 轉換為業務邏輯。要使用Action,請創建它的子類並覆蓋 process()方法。


ActionServlet (Command) 使用 perform()方法將參數化的類傳遞給 ActionForm。仍然沒有太多討厭的request.getParameter()調用。當事件進展到這一步時,輸入表單數據(或 HTML表單數據)已被從請求流中提取出來並轉移到 ActionForm類中。

註:擴展 Action 類時請注意簡潔。Action類應該控制應用程序的流程,而不應該控制應用程序的邏輯。通過將業務邏輯放在單獨的包或EJB 中,我們就可以提供更大的靈活性和可重用性。

考慮 Action 類的另一種方式是 Adapter設計模式。Action的用途是「將類的接口轉換為客戶機所需的另一個接口。Adapter使類能夠協同工作,如果沒有Adapter,則這些類會因為不兼容的接口而無法協同工作。」(摘自 Gof所著的 Design Patterns - Elements of Reusable OOSoftware )。本例中的客戶機是ActionServlet,它對我們的具體業務類接口一無所知。因此,Struts提供了它能夠理解的一個業務接口,即 Action。通過擴展Action,我們使得我們的業務接口與 Struts業務接口保持兼容。(一個有趣的發現是, Action是類而不是接口)。Action開始為一個接口,後來卻變成了一個類。真是金無足赤。)

Error 類
UML 圖(圖 6)還包括 ActionError 和ActionErrors。ActionError封裝了單個錯誤消息。ActionErrors 是ActionError 類的容器,View可以使用標記訪問這些類。ActionError 是 Struts保持錯誤列表的方式。

圖 7. Command (ActionServlet)與 Model (Action) 之間的關係的 UML 圖

ActionServlet 與 Action 的關係

ActionMapping 類
輸入事件通常是在 HTTP 請求表單中發生的,servlet 容器將 HTTP請求轉換為HttpServletRequest。控制器查看輸入事件並將請求分派給某個Action 類。struts-config.xml 確定Controller 調用哪個 Action類。struts-config.xml 配置信息被轉換為一組ActionMapping,而後者又被放入ActionMappings 容器中。(您可能尚未注意到這一點,以 s 結尾的類就是容器)

ActionMapping 包含有關特定事件如何映射到特定Action 的信息。ActionServlet (Command)通過 perform() 方法將 ActionMapping傳遞給 Action 類。這樣就使 Action可訪問用於控制流程的信息。

ActionMappings
ActionMappings 是 ActionMapping對象的一個集合。

再訪郵件列表樣例
下面我們看一下 Struts 是如何解決困擾 join.jsp的這些問題的。改寫後的方案由兩個項目組成。第一個項目包含應用程序的邏輯部分,這個應用程序是獨立於Web 應用程序的。這個獨立層可能是用 EJB技術實現的公共服務層。為了便於說明,我使用 Ant構建進程創建了一個稱為 business的包。有幾個原因促使我們使用獨立的業務層:

  • 劃分責任
    單獨的包使管理人員能夠在開發小組內委派責任。這也有助於提高開發人員的責任心。

  • 通用件

    我們設想開發人員將這個包看作一個商業軟件。將它放在另外的包中使它更像通用件。這個包可能是通用件,也可能是由組織內部的另一個小組開發的。

  • 避免不必要的構建和單元測試。
    分開的構建進程有助於避免不必要的構建和單元測試。

  • 使用接口開發
    在進行開發和避免不必要的耦合時,它有助於從接口的觀點來思考問題。這是極重要的一個方面。當開發您自己的業務包時,這些業務類不應該關心到底是Web應用程序執行調用,還是獨立應用程序執行調用。因此,應該避免在業務邏輯層使用對servlet API 或 Struts API 調用的任何引用。

  • 穩定性
    並不是每個組織都每天、每週甚至每月進行檢修。因此,在進行開發時,穩定的接口點是重要的。不能因為業務包處於變遷階段就認為Web 項目也應該處於變遷階段。

業務構建註釋
我用 Ant 構建項目,並用 JUnit 運行單元測試。business.zip包含構建業務項目所需的一切,當然 Ant 和 JUnit除外。這個包腳本將構建類,運行單元測試,創建 Java 文檔和 jar文件,最後將所有這些內容壓縮到一個 zip 文件中發送給客戶。只要對build.xml作一些修改,您就可以將它部署到其他平台上。Business.jar位於 Web 的下載部分,因此,您並非必須下載並構建這個業務包。

Web 項目
第二個項目是用 Struts 開發的一個 Web 應用程序。您將需要一個符合 JSP1.1 和 Servlet 2.2 規範的容器。最快的入門方法是下載並安裝 Tomcat3.2(請參閱 參考資源 )。直到有 Struts 的1.0 發行版之前,我建議您從 Jakarta 項目獲得最新的版本(請參閱 參考資源
)。這對我來說是個大問題,我不能確保我的Web 項目樣例能與您下載的 Struts 一起工作。Struts仍在不斷變化,所以我不得不經常更新我的項目。在本項目中,我使用的是jakarta-struts-20010105.zip。圖 8 顯示了此 Web項目的結構。如果您已安裝了 Ant,則運行這個版本將創建一個稱為joinStruts.war 的 war文件,您隨時可以部署這個文件。

圖 8. Web項目的結構
Web 項目的結構

清單 4 顯示了轉換後的 JSP 文件,稱為joinMVC.jsp。這個文件從最初的 50 行變為 19行,並且現在不含任何 Java代碼。從網頁設計人員的角度來看,這是個巨大的改進。

清單 4. joinMVC.jsp -- 再訪簡單的 JSP

            <%@ page language="java" %>
              <%@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %>
                <%@ taglib uri="/WEB-INF/struts-form.tld" prefix="form" %>
                  <html>
                    <head>
                      <title>
                        <struts:message key="join.title"/>
                      </title>
                    </head>
                    <body bgcolor="white">
                      <form:errors/>
                      <h3>Enter your email to join the group</h3>
                      <form:form action="join.do" focus="email" >
                        <form:text property="email" size="30" maxlength="30"/>
                        <form:submit property="submit" value="Submit"/>
                        </form:form>
                    </body>
                  </html> 

網頁的變化
下面是使用 Struts 標記庫之後所發生變化的列表:

  • Import
                        <%@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %>
                          
    用於 Java 代碼的<%@page import? 已被替換為用於Struts 標記庫的 <%@ taglib uri?。

  • 文本
                            <struts:message key="join.title"/>
                            
    資源屬性文件包含 join.title的文本。在本例中,ApplicationResources屬性文件包含這個名值對。這使字符串更易於查看和國際化。

  • 錯誤
                            <form:errors/>
                            
    ActionServlet 或 ActionForm構建要顯示的錯誤消息。這些錯誤消息也可以包含在屬性文件中。ApplicationResources也提供了一種格式化錯誤的方法,即設置 error.header 和error.footer。

  • HTML 表單
                            <form:form action="join.do" focus="email" >
                              
    • JSP<form> 標記和屬性替代了 HTML<form> 標記和屬性。<formaction="join.jsp" name="join"> 已更改為<form:form action="join.do" focus="email"> 。
    • HTML 標記已替換為<form:text/> 。
    • HTML 標記已替換為<form:submit/> 。

模型 -- 會話狀態
JoinForm 擴展了 ActionForm并包含表單數據。本例中的表單數據只有電子郵件地址。我已為電子郵件地址添加了一個寫方法和讀方法,以供框架訪問。為了便於說明,我重寫了validate() 方法,並使用了 Struts 的跟蹤功能。Struts將創建 JoinForm 並設置狀態信息。

模型 -- 業務邏輯
如前所述,Action是控制器和實際業務對象之間的接口。JoinAction 包裝了對business.jar 的調用,這些調用最初在join.jsp 文件中。JoinAction 的perform() 方法在清單 5 中列表。

清單 5. - JoinAction.perform()

public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) 
throws IOException, ServletException { // 抽取我們將會用到的屬性和參數 
JoinForm joinForm = (JoinForm) form; 
String email = joinForm.getEmail(); 
ActionErrors errors = new ActionErrors(); // 存儲輸入.... 
try { business.db.MailingList.AddEmail(email); } 
catch (Exception e) { // 記錄日誌,打印棧 // 將錯誤回顯給用戶 
errors.add("email",new ActionError("error.mailing.db.add")); } 
// 如需任何消息,請將指定的錯誤消息鍵保存到 //HTTP 請求中,以供<struts:errors> 標記使用。 
if (!errors.empty()) { saveErrors(request, errors); // 返回到初始表單 
return (new ActionForward(mapping.getInput())); } // 將控制權轉交給 Action.xml 中指定的 'success' URI 
return (mapping.findForward("success")); } 

註:perform() 返回一個稱為ActionForward的類,該類通知控制器下一步該執行什麼操作。在本例中,我使用從控制器傳入的映射來決定下一步的操作。

控製器
我已修改了 JSP文件,並創建了兩個新類:一個類用來包含表單數據,一個類用來調用業務包。最後,我通過修改配置文件struts-config.xml 將它們整合起來。清單 6顯示了我添加的 action 元素,這個元素用來控制joinMVC.jsp 的流程。

清單 6. Action 配置


                    <actionpath="/join"  name="joinForm"  type="web.mailinglist.JoinAction" 
                    scope="request" input="/joinMVC.jsp"  validate="true">
                    <forwardname="success"path="/welcome.html"/>
                    </action> 

action 元素描述了從請求路徑到相應的 Action類的映射,應該用這些類來處理來自這個路徑的請求。每個請求類型都應該有相應的action 元素,用來描述如何處理該請求。對於 join 請求:

  1. joinForm 用來容納表單數據。
  2. 因為 validate 被標記為 true,所以 joinForm將試圖進行自我驗證。
  3. web.mailinglist.JoinAction是用來處理對這個映射的請求的 action 類。
  4. 如果一切順利,該請求將轉到 welcome.jsp。
  5. 如果出現業務邏輯故障,流程將返回到joinMVC.jsp,這是最初發出請求的網頁。為什麼會這樣呢?在清單6 的 action 元素中,有一個稱為 input 的屬性,其值為"/joinMVC.jsp"。在我的JoinAction.perform()(如清單 5所示)中,如果業務邏輯失敗,perform() 就返回一個ActionForward,並以 mapping.getInput()作為參數。本例中的 getInput() 是"/joinMVC.jsp"。如果業務邏輯失敗,它將返回到joinMVC.jsp,這是最初發出請求的網頁。

使用 Struts 前後的比較
正如我們在圖 9 中所看到的那樣,複雜性和層都有顯著增加。不再存在從JSP 文件到 Service 層的直接調用。

圖 9. 使用 Struts前後的比較
使用 Struts 前後的比較

Struts 的優點

  • JSP 標記機制的使用

    標記特性從 JSP 文件獲得可重用代碼和抽象 Java代碼。這個特性能很好地集成到基於 JSP的開發工具中,這些工具允許用標記編寫代碼。

  • 標記庫
    為什麼要另發明一種輪子,或標記庫呢?如果您在庫中找不到您所要的標記,那就自己定義吧。此外,如果您正在學習JSP 標記技術,則 Struts 為您提供了一個起點。

  • 開放源碼
    您可以獲得開放源碼的全部優點,比如可以查看代碼並讓使用庫的每個人檢查代碼。許多人都可以進行很好的代碼檢查。

  • MVC 實現樣例
    如果您希望創建您自己的 MVC 實現,則 Struts 可增加您的見識。

  • 管理問題空間
    分治是解決問題並使問題可管理的極好方法。當然,這是一把雙刃劍。問題越來越複雜,並且需要越來越多的管理。

Struts 的缺點

  • 仍處於發展初期
    Struts 開發仍處於初級階段。他們正在向著發行版本 1.0而努力,但與任何 1.0 版本一樣,它不可能盡善盡美。

  • 仍在變化中
    這個框架仍在快速變化。Struts 1.0 與 Struts 0.5相比變化極大。為了避免使用不贊成使用的方法,您可能隔一天就需要下載最新的Struts。在過去的 6 個月中,我目睹 Struts 庫從 90K 增大到 270K以上。由於 Struts中的變化,我不得不數次修改我的示例,但我不保證我的示例能與您下載的Struts 協同工作。

  • 正確的抽象級別

    Struts是否提供了正確的抽象級別?對於網頁設計人員而言,什麼是正確的抽象級別呢?這是一個用$64K的文字才能解釋清楚的問題。在開發網頁的過程中,我們是否應該讓網頁設計人員訪問Java 代碼?某些框架(如 Velocity)說不應該,但它提供了另一種 Web開發語言讓我們學習。在 UI 開發中限制訪問 Java有一定的合理性。最重要的是,如果讓網頁設計人員使用一點Java,他將使用大量的 Java。在 Microsoft ASP的開發中,我總是看到這樣的情況。在 ASP 開發中,您應該創建 COM對象,然後編寫少量的 ASP 腳本將這些 COM 對象聯繫起來。但是,ASP開發人員會瘋狂地使用 ASP 腳本。我會聽到這樣的話,「既然我可以用VBScript 直接編寫 COM 對象,為什麼還要等 COM開發人員來創建它呢?」通過使用標記庫,Struts 有助於限制 JSP文件中所需的 Java 代碼的數量。Logic Tag就是這樣的一種庫,它對有條件地生成輸出進行管理,但這並不能阻止 UI開發人員對 Java代碼的狂熱。無論您決定使用哪種類型的框架,您都應該了解您要在其中部署和維護該框架的環境。當然,這項任務真是說起來容易做起來難。

  • 有限的適用範圍
    Struts 是一種基於 Web 的 MVC 解決方案,所以必須用 HTML、JSP 文件和servlet 來實現它。

  • J2EE 應用程序支持
    Struts 需要支持 JSP 1.1 和 Servlet 2.2 規範的 servlet容器。僅憑這一點遠不能解決您的全部安裝問題,除非使用 Tomcat3.2。我用 Netscape iPlanet 6.0安裝這個庫時遇到一大堆問題,按理說它是第一種符合 J2EE的應用程序服務器。我建議您在遇到問題時訪問 Struts用戶郵件列表的歸檔資料(請參閱 參考資源 )。

  • 複雜性
    在將問題分為幾個部分的同時也引入了複雜性。毫無疑問,要理解 Struts必須接受一定的培訓。隨著變化的不斷加入,這有時會令人很沮喪。歡迎訪問本網站。

  • 在何處...

    我還能指出其他問題,例如,控制器的客戶端驗證、可適用工作流程和動態策略模式在什麼地方?但是,目前這太容易成為吹毛求疵的問題,有些問題是無關緊要的,或者說應該對1.0 發行版提這些問題。隨著 Struts 小組的不斷努力,到您閱讀本文時Struts 說不定已經有了這些功能,或者它很快就會具有這些功能。

Struts 的前景
在這個軟件開發的新時代,一切都變得很快。在不到 5年的時間內,我已經目睹了從 cgi/perl 到 ISAPI/NSAPI、再到使用 VB 的ASP、一直到現在的 Java 和 J2EE 的變遷。Sun 正在盡力將新的變化反映到JSP/servlet 體系結構中,正如他們對 Java 語言和 API所作的更改一樣。您可以從 Sun 的網站獲得新的 JSP 1.2 和 Servlet 2.3規範的草案。此外,一個標準 JSP標記庫即將出現;有關這些規範和標記庫的鏈接,請參閱 參考資源

最後的註釋
Struts 使用標記和 MVC解決了某些重大問題。這個方法有助於提高代碼的可重用性和靈活性。通過將問題劃分為更小的組件,當技術空間或問題空間中出現變化時,您就有更多的機會重用代碼。此外,Struts使網頁設計人員和 Java開發人員能將精力集中於自己最擅長的方面。但是,在強健性增強的同時,也意味著複雜性的增加。Struts比簡單的單個 JSP 網頁要複雜得多,但對於更大的系統而言,Struts實際上有助於管理複雜性。另外,我並不想編寫自己的 MVC實現,而只想了解一個這樣的實現。不管您是否會使用 Struts,回顧這個Struts 框架(對不起,應該是庫)都會使您對 JSP 文件和 servlet的特性、以及如何將它們組合起來用於您的下一個 Web項目有更好的了解。正像翼間支柱是機翼結構中不可缺少的一部分一樣,Strut也可能成為您下一個 Web 項目的不可缺少的一部分。


參考資源

作者簡介
Malcolm G. Davis住在阿拉巴馬州伯明翰市,他在自己的諮詢公司當總裁。他自稱是一名 Java傳道者。他在宣傳 Java的優點的閒暇之餘,他會去長跑,或者與自己的孩子一起玩。可以通過 malcolm@nuearth.com 與Malcolm 聯繫。

內容圖示
url email imgsrc image code quote
樣本
bold italic underline linethrough   












 [詳情...]
validation picture

注意事項:
預覽不需輸入認證碼,僅真正發送文章時才會檢查驗證碼。
認證碼有效期10分鐘,若輸入資料超過10分鐘,請您備份內容後,重新整理本頁並貼回您的內容,再輸入驗證碼送出。

選項

Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|