<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Sung in Blog

               一些技術(shù)文章 & 一些生活雜碎
    一、摘要

    建立和維護(hù)企業(yè)應(yīng)用程序非常困難。而為這些應(yīng)用設(shè)計出上乘的、易于維護(hù)的用戶界面則是所有工作中最讓人畏懼的任務(wù)。來自Apache Jakarta 項目的Struts框架為J2EE(Java2平臺企業(yè)版)帶來了Model 2 結(jié)構(gòu)。在本文中,兩位作者討論了開發(fā)者在使用Struts 的過程中所遇到的問題,以及簡化這些問題的相應(yīng)方法。

    除非你過去幾年內(nèi)潛居于石洞之中,否則你不可能沒聽說過Struts framework。Struts是由Apache軟件基金會最初發(fā)起的開源,主要是為了促進(jìn)Web應(yīng)用演示層內(nèi)的模型-視圖-控制器(MVC)設(shè)計范例。truts 提供了使用Service的MVC模式給Worker 模式。一個設(shè)計優(yōu)秀的結(jié)構(gòu)總是力爭耦合寬松、結(jié)合性高。Struts為在多捆綁的企業(yè)Web應(yīng)用的演示層實現(xiàn)這個目標(biāo)提供了一個機(jī)制。 實現(xiàn)企業(yè)應(yīng)用結(jié)構(gòu)所面對的最讓人望而生畏的任務(wù)之一就是演示層的創(chuàng)建和維護(hù)。用戶期望得到非常功能化的、堅固的、和優(yōu)雅的灰土用戶界面。因此,演示層的代碼庫使得應(yīng)用層超負(fù)荷運行。另外,不同的顯示平臺如無線電話和PDAs 的出現(xiàn)使得原本復(fù)雜的狀況更加復(fù)雜的多。

    各種不同的書和文章已經(jīng)講述了Struts的內(nèi)部工作原理并且教我們?nèi)绾问褂眠@個框架。本文詳細(xì)闡述了使用Struts 的Web應(yīng)用開發(fā)者所遇到的問題,以及如何解決這些問題。下列方法中有許多可以應(yīng)用到不同的MVC框架中如即將上市的JavaServer Faces 規(guī)范。 Craig R. McClanahan,Struts的創(chuàng)始人之一,造就了這個規(guī)范。

    本討論的主題包括:在使用Struts框架,用BEA WebLogic Server建立J2EE(Java2平臺企業(yè)版)應(yīng)用的過程中出現(xiàn)最多問題的所有區(qū)域。我們將討論下列專題:
    ·創(chuàng)建/維護(hù) struts-config.xml
    ·表格/會話期管理
    ·Struts 映射和用戶界面的關(guān)系
    ·管理Back按鈕
    ·用戶認(rèn)證
    ·用戶界面控制流程
    · 異常處理
    ·測試

    二、挑兩個,早上呼我

    Struts框架毫無疑問,減輕了企業(yè)應(yīng)用程序的用戶界面的開發(fā)和維護(hù)。但是,即使只是在一個簡單的應(yīng)用中使用了Struts ,開發(fā)者也會迅速的認(rèn)識到struts-config.xml這個惡魔。 這個文件很有可能迅速變得難于處理。在建立企業(yè)應(yīng)用時,struts-config.xml 能夠多出 500個動作映射,使得自身變得真正地難于管理。

    我們推薦兩個工具來幫助治理這個頭疼的問題。首先,使用來自Alien-Factory 的Microsoft Visio 和StrutsGUI 文檔化你的用戶界面流程。StrutsGUI是一個Visio 模版,它對使用Struts 術(shù)語描述用戶流程圖有幫助。在Struts 模版內(nèi)有一個隱藏的功能:只要右鍵點擊該項,選擇Edit Title Properties,然后選擇Tools項,你就能夠在該圖的基礎(chǔ)上生成struts-config.xml 文件。例如,圖1中顯示的簡單應(yīng)用生成了如下列代碼所示的struts-config.xml :



    Figure 1. StrutsGUI model. Click on thumbnail to view full-size image.


    <?xml version="1.0" encoding="ISO-8859-1" ?>
    
    <!-- Struts Config XML - Sample Struts App -->
    <!-- ===================================== -->
    
    <!-- AutoGenerated from : c:\dev\javaworld\app\sample.vsd -->
    <!-- AutoGenerated on   : 02-18-2003 23:05:47 -->
    <!-- AutoGenerated by   : Struts GUI v2.11   (c)2002 Alien-Factory -->
    <!--                    : See 'http://www.alien-factory.co.uk' for details -->
    
    <!-- GET YOUR STICKY FINGERS OFF! i.e. Do not edit. -->
    
    <!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 Bean Definitions =================== -->
      <form-beans>
      </form-beans>
    
      <!-- ================= Global Forward Definitions =================== -->
      <global-forwards>
      </global-forwards>
    
      <!-- ======================= Action Definitions ===================== -->
      <action-mappings>
        <action  path="/Login"
                 type="com.agilquest.onboard.presentation.actions.LoginAction">
          <description>Authenticates and authorizes a user.</description>
        </action>
      </action-mappings>
      
    </struts-config>


    為了使你的用戶界面流程圖更加復(fù)雜,我們推薦在使用StrutsGUI 時增加一個步驟。在你的StrutsGUI Visio 文檔內(nèi),你可以輕易的將每個JSP (JavaServer Pages)頁鏈接到它在應(yīng)用中的實際屏幕快照。創(chuàng)建這個界面不但確實有助于應(yīng)用程序的文檔化,更重要的是,它成為了培訓(xùn)新的從事用戶界面設(shè)計的開發(fā)者的一件極好的工具。

    另一個幫助管理Struts應(yīng)用的工具就是由James Holmes 發(fā)明的Struts Console。本質(zhì)上,這個工具提供了一組設(shè)備,這些設(shè)備使你能夠得到與StrutsGUI 相同的終點,但是它們在途徑和長度上有區(qū)別。這兩個工具都執(zhí)行良好,其中任何一個都可以增強(qiáng)基于Struts的企業(yè)應(yīng)用的可維護(hù)性。

    三、現(xiàn)在,我將表格放在哪里?

    ActionForm 會話期管理有點棘手。ActionForm的周期怎樣?它在請求周期內(nèi)或者會話期周期內(nèi)嗎?為了得到它所代表的功能周期,方案之一就是將ActionForm置于會話期之內(nèi)。在這種情況下,你通常怎樣維護(hù)這些ActionForm 對象呢?誰知道不再需要他們時刪除他們要承擔(dān)什么責(zé)任呢?典型的情況是:用戶通過菜單從一個功能轉(zhuǎn)為使用另一個功能。在這種情況下,原來的ActionForm 對象就應(yīng)該從會話期刪除,并且創(chuàng)建新的ActionForm 對象。這時還應(yīng)該出現(xiàn)一個集中的Action類,MenuAction,它只處理菜單切換。這個Action 類從會話期刪除多余的ActionForm 對象。然后將用戶前進(jìn)到創(chuàng)建新ActionForm 對象所在的新頁面。

    在這種情況下,站在用戶的立場上或者基于用戶權(quán)限,我們應(yīng)該如何顯示不同的菜單項呢?這個菜單也應(yīng)該國際化,并且它修改時應(yīng)該以用戶權(quán)限為基礎(chǔ);也就是說,如果許可修改了,菜單也要相應(yīng)的修改。有一種方法可以持續(xù)用戶的權(quán)限。當(dāng)用戶注冊時, MenuFactory根據(jù)這些權(quán)限創(chuàng)建菜單,為了增加安全性, MenuAction類在允許用戶進(jìn)行到他所選擇的功能之前需要認(rèn)證用戶。命名struts-config.xml 中的ActionForm 對象的首要規(guī)則是對象名以Form 結(jié)束,從而簡化了會話期內(nèi)這些表格的維護(hù)。例如: ReservationForm, SearchUserForm, BankAccountForm, UserProfileForm,等等。

    下列代碼描述了一個具有Action 映射的普通菜單切換動作,它進(jìn)一步闡明了ActionForm(s)管理:

    public class MenuAction {
    
      public ActionForward perform(ActionMapping       _mapping,
                                   ActionForm          _form,
                                   HttpServletRequest  _request,
                                   HttpServletResponse _response)
                                      throws IOException, ServletException {
    
        // Check end-user permissions whether allowed into the requested     
        // functionality 
        checkIfUserAllowedToProceed(_mapping, _form, _request, _response); 
    
        // Clean up the session object (this logic is in its own method)
        String formName = null; 
    
        HttpSession session = _request.getSession();
        Enumeration e = session.getAttributeNames();  
    
        while(e.hasMoreElements()) {
         
          formName = (String)e.nextElement();
    
          if (formName.endsWith("Form")){
            session.removeAttribute(formName);
          }    
        }
    
        // Now find out which functionality the end-user wants to go to
        String forwardStr = _request.getParameter("nextFunctionality");
    
        if (forwardStr != null && forwardStr.trim().length() > 0){
          return _mapping.findForward(forwardStr);
        }
        else {
          return _mapping.findForward("index");
        }
      }  
    }


    下列Action映射就是一個闡述如何以菜單選擇為基礎(chǔ)實現(xiàn)動作的例子:

    <!-- A generic menu action that forwards the user from one 
         functionality to another functionality (after checking permissions)
    -->
    <action path="/menuAction"
            type="x.y.z.MenuAction"
            input="/menu.jsp">      
      <forward name="create_reservation" path="/actionResv.do"/> 
      <forward name="index"              path="/menu.jsp"/> 
      <forward name="add_person"         path="/actionPerson.do"/> 
      <forward name="logout"             path="/actionLogout.do"/> 
    </action>


    例子和映射都是可以自我解釋的。

    四、再說一次,我們是怎樣關(guān)聯(lián)的?

    任何JSP頁的許多輸入點與許多現(xiàn)有點之間都有一個關(guān)系,這取決于頁面本身的復(fù)雜程度。認(rèn)識到這些關(guān)系對于理解和維護(hù)用戶界面是至關(guān)重要的。我們已經(jīng)將JSP頁和Action 類之間的關(guān)系定義為:
    ·1:1 關(guān)系
    ·1:N 關(guān)系
    ·N:N關(guān)系

    1:1 關(guān)系 在1:1 關(guān)系中,用戶通過Action類從一個JSP頁切換到另一個頁面;這就使得JSP頁和Action 之間容易形成一個緊密的耦合。唯一的額外開銷就是struts-config.xml 中有一個Action映射。這個在struts-config.xml 中只有一個Action 映射的簡單Action 可用于從一個頁面切換到另一個頁面。直接通過一個JSP頁訪問另一個JSP頁是不太現(xiàn)實的;他不能夠檢查轉(zhuǎn)向目標(biāo)JSP頁的用戶權(quán)限(如果可行的話)。他還導(dǎo)致了維護(hù)方面的問題。為了避免這些問題,可以總是通過Action 類從一個JSP頁轉(zhuǎn)向另一個JSP頁:

    <!-- A generic action that forwards request from one JSP page to another JSP page -->
    <action path="/forwardAction"
            type="x.y.z.One2OneAction"
            input="/test1.jsp">      
      <forward name="continue"  path="/test2.jsp"/> 
    </action>


    1:N關(guān)系 稍微復(fù)雜一點的關(guān)系就是JSP頁有多個現(xiàn)有點但是只有一個輸入點,也叫做1:N關(guān)系。在這種情況下,總是使用一個單一 Action類分支到不同的目標(biāo)。這就保證了Action 在將用戶推進(jìn)到目標(biāo)之前能夠檢查不同的情況或者權(quán)限。唯一的額外開銷就是在struts-config.xml 中有一個Action 映射。這也推動了JSP頁與Action 映射之間的1:1 映射。下面的Action映射標(biāo)出了一個映射,它有一個單一輸入點和多個前推,多個前推代表著多個現(xiàn)有點:

    <!-- A generic action that forwards request from one JSP page to different 
         branches depending on the selected hyperlink, by the end-user
    -->
    <action path="/branchAction"
             type="x.y.z.One2NAction"
             input="/test1.jsp">      
      <forward name="target1"   path="/test2.jps"/> 
      <forward name="target2"   path="/test3.jsp"/> 
      <forward name="target3"   path="/someAction.do"/> 
    </action>


    N:N 關(guān)系 最復(fù)雜的關(guān)系,即N:N關(guān)系,指的是JSP頁或者Action 類有多個輸入點和多個現(xiàn)有點。N:N 關(guān)系是頻繁出現(xiàn)在企業(yè)應(yīng)用程序中的一個有趣和復(fù)雜的部分。N:N關(guān)系最初應(yīng)用在不同的JSP頁訪問一個公共JSP頁或者一個公共Action類的情況下。假設(shè)用戶進(jìn)入的JSP頁是一個網(wǎng)絡(luò)中心(特別是這個JSP頁由不同的JSP頁都可到達(dá)),但是用戶又想返回或者取消這個流程;那么開發(fā)者就處于進(jìn)退兩難的局面:不知道怎樣將用戶送往正確的頁面。

    另一個場景是:Action類接合到數(shù)據(jù)庫(通過不同的功能函數(shù)或者JSP頁),并且出現(xiàn)錯誤。以用戶原來所在的位置為基礎(chǔ),將用戶發(fā)送回原來所在的位置或者適當(dāng)前推,這需要仔細(xì)推敲。struts-config.xml映射證明是沒有幫助的,因為輸入域是一個確定的JSP頁或者 Action 類。我們創(chuàng)建的結(jié)構(gòu)應(yīng)該足夠靈活,這樣開發(fā)者不必在struts-config.xml 折騰就能夠輕而易舉的修改流程邏輯。這就是N:N關(guān)系所要解決的問題。通過實現(xiàn)一個能夠靈活發(fā)送用戶到目標(biāo)所在地或者目的文件的界面,這個值修改起來就比較容易。下面的Action映射給出的映射有多個輸入點和多個前推,這些前推代表多個現(xiàn)有點:

    public class N2NAction {
    
      public ActionForward perform(ActionMapping      _mapping,
                                   ActionForm         _form,
                                   HttpServletRequest _request,
                                   HttpServletResponse _response)
                                      throws IOException, ServletException {
    
        N2NInterface if = (N2NInterface)_form;
    
        //Execute some business functionality here
        try{
          //Business logic successful?
                   
        }
        catch(Exception e){
    
          //Indicates failure
          return _mapping.findForward(if.getSource()); 
        }
    
        //Indicates success
        return _mapping.findForward(if.getDestination());            
    
      } 
    
    }
    
    <!-- A generic action that forwards request from one JSP page to another JSP page -->
    <action  path="/sourceAndDestinationAction"
             type="x.y.z.N2NAction"
             input="/test1.JSP">      
      <forward name="source1"          path="/source1.JSP"/> 
      <forward name="source2"          path="/source2.JSP"/> 
      <forward name="source3"          path="/someAction.do"/> 
      <forward name="destination1"     path="/destination1.JSP"/> 
      <forward name="destination2"     path="/destination1.JSP"/> 
      <forward name="destination3"     path="/destination2.JSP"/>
    </action>
    
       A hyerplink can be something like
       <a href="sourceAndDestinationAction.do?
        source=source1&destination=destination1">click me</a>
       <a href="sourceAndDestinationAction.do?
        source=source2&destination=destination2">click me too</a>



    所有的ActionForms 默認(rèn)地都必須所有這三種關(guān)系(通常通過界面)。使用普通的Action 類,你可以自由地在用戶界面流程中移動.

    .

    目錄:
    五、Back之痛!
    六、你是誰,在這做什么?
    七、我們?nèi)ネ翁帲?/A>
    八、犯錯乃人之常情...我們不是圣賢
    九、測試,就是用戶想要的!
    十、簡化Struts 開發(fā)


    五、Back之痛!

    設(shè)計演示層,有一個好方法就是按照功能設(shè)計。例如:在一個預(yù)訂系統(tǒng)中預(yù)訂的時候,將所有的相關(guān)動作類封裝到一個包裝內(nèi)如

    com.companyname.productname.presentation.
       reservation.mak


    就是一個不錯的方法。深度封裝也可以應(yīng)用到ActionForm類中。表格應(yīng)該處在功能周期的會話期內(nèi)。這就保證了該完整功能所需的數(shù)據(jù)放在表格對象本身之內(nèi)。這樣用戶就能夠前進(jìn)到功能的任何頁面并且找到該頁上顯示的正確數(shù)據(jù)。接著用戶還能夠在最終保存該數(shù)據(jù)之前更新數(shù)值。因此,就會產(chǎn)生一個有趣的兩難局面:當(dāng)用戶確認(rèn)數(shù)據(jù)、按下瀏覽器中的Back 按鈕、修改并再次提交的話會發(fā)生什么事情?例如,在創(chuàng)建了數(shù)據(jù)庫中的預(yù)定后,用戶返回并試圖再次提交同樣的數(shù)據(jù)。演示層必須在應(yīng)用層有機(jī)會抱怨之前先捕捉到這個錯誤。處理這種情況的方法之一就是在提交之前創(chuàng)建一個令牌,提交之后檢查令牌的有效性,并立即修改令牌值——這樣用戶就不能夠再次使用Back 按鈕來提交同樣的值。

    這個方法的弊病之一就是需要管理令牌:例如,如果用戶試圖保存數(shù)據(jù)失敗了,但是令牌值卻已經(jīng)修改了。如果這樣的話,用戶就不能夠修改數(shù)據(jù),和在不重新設(shè)置令牌的情況下重新提交。相應(yīng)的Action 類也不會允許提交。那么到底什么時候才應(yīng)該重置令牌呢?用戶可以遍歷六個頁面,那么在確認(rèn)它的修改時就會收到錯誤,然后定向到六個頁面中的任何一個頁面。

    要管理這個問題,就需要在用戶請求一個特別功能時創(chuàng)建一個表格并在會話期內(nèi)存儲一個默認(rèn)的令牌值。在保存之前,用戶可以多次使用Back按鈕進(jìn)行修改。一旦用戶提交了這些修改,只有在保存成功之后才能重新設(shè)置令牌。如果確認(rèn)失敗,用戶可以使用Back 按鈕或者前進(jìn)到產(chǎn)生失敗的頁面,修改數(shù)據(jù)然后重新提交數(shù)據(jù)。一旦確認(rèn)成功的話,令牌值就會修改。ActionForm 對象本身也可以包含令牌值(令牌值可以通過程序設(shè)置)。還有一個方法就是,在第一次提交之后,Submit 按鈕就變得無效、不允許用戶再次提交直到有事情發(fā)生。我們建議每個ActionForm 處理他自己的令牌,應(yīng)用至多是使用不止一個不同的ActionForm對象來處理一個特殊功能。

    要了解另外一個復(fù)制表格提交的方法,請參考Romain Guay的 (JavaWorld, March 2003).

    六、你是誰,在這做什么?

    企業(yè)應(yīng)用必須設(shè)計成能夠同時支持多個認(rèn)證模式。這對于來自ISVs(獨立的軟件開發(fā)商)的軟件更為重要。例如,假設(shè)一個應(yīng)用的認(rèn)證要求是單一登錄、詢問用戶密碼、條形碼認(rèn)證或者指紋認(rèn)證,甚至是將來有可能出現(xiàn)的聲音認(rèn)證。JAAS (Java 認(rèn)證和授權(quán)服務(wù)),這個可插入的認(rèn)證機(jī)制,證明可用于這個方面。默認(rèn)的, Struts 1.1 支持JAAS。JAAS也可用在具有極好結(jié)果的Struts 1.0中。對于認(rèn)證,一個很好的繼承性設(shè)計將會推動使用不同的認(rèn)證動作類,每個動作類都有他自己唯一的Action 映射。這種設(shè)計方法將會推動對不同認(rèn)證的同時支持。如果需要添加新的認(rèn)證機(jī)制,只要用一個支持該認(rèn)證的Action類在struts-config.xml內(nèi)創(chuàng)建一個新的動作映射即可。

    七、我們?nèi)ネ翁帲?/B>

    流程控制器的設(shè)計目的是限制和引導(dǎo)用戶通過應(yīng)用程序,它在保證用戶遵循特殊流程方面很實用。讓流程控制器以系統(tǒng)的地位為基礎(chǔ)證明是有用的。無論用戶什么時候試圖訪問系統(tǒng)中的功能,流程控制器都可以確保用戶有權(quán)進(jìn)入到特殊流程中。而且,就算出現(xiàn)了意外情況,用戶也能夠被引導(dǎo)到恰當(dāng)?shù)捻撁妗7胖昧鞒炭刂破髯詈玫牡胤绞窃诔愔小V挥性诹鞒炭刂破鳚M意之后用戶才允許執(zhí)行特定動作。

    圖 2 給出了一個簡單的繼承性模型,它可用來使用合并到用戶認(rèn)證中的流程控制器。



    Figure 2. Simple authentication class model



    八、犯錯乃人之常情...我們不是圣賢

    Struts框架通過ActionError和ActionErrors類為我們提供了異常處理結(jié)構(gòu)。 ActionError就是——存在于Action 或者ActionForm類中的錯誤,或者應(yīng)用層給出的錯誤。ActionError 類典型地可通過使用簡單的鑰匙構(gòu)造,或者通過使用鑰匙/值對來構(gòu)造。如果你的應(yīng)用有國際化關(guān)系,那么該鑰匙可用于查找國際化信息資源數(shù)據(jù)庫。如果這些國際化關(guān)系不存在的話,那么取代值可用于顯示錯誤信息。至多有四個占位符設(shè)置在對象排列中,每個占位符都包含整個錯誤信息的一個單獨部分。這些值可構(gòu)造得與MessageFormatter 類相似。

    ActionErrors類,擴(kuò)展了ActionMessage 類,它是具有單一公共方法的ActionError 類的集合,這個單一公共方法是add(java.lang.String property, ActionError error)。這個方法簽名中的第二個參數(shù)是直接的:他指的是已經(jīng)存在的真實錯誤(ActionError)。通過將錯誤信息與指定的域關(guān)聯(lián)起來,屬性參數(shù)可用于域級別的校驗。既然錯誤信息與指定域關(guān)聯(lián),你可以輕易地將信息定位于有疑問的域附近或者定位于它能產(chǎn)生最大意義的任何地方。例如,如果你在用戶的邏輯標(biāo)記符之上進(jìn)行域級別的校驗,并且在類LoginAction 中出現(xiàn)錯誤,你可以使用下列代碼片斷:

    ActionErrors errors = new ActionErrors();
    errors.add("logiinID", new ActionError("loginID.invalid"));
    saveErrors(_request, errors);
    return (new ActionForward(_mapping.getInput()));


    字符串"loginID.invalid"就是用于信息資源數(shù)據(jù)庫中國際化字符串值的鑰匙。為了顯示錯誤信息,在你的login.jsp中,使用下列HTML:

    <font color="red"><html:errors property="loginID"/></font>


    有了對用于異常和異常鏈的Struts 框架設(shè)備的這個特別理解,要管理整個企業(yè)應(yīng)用結(jié)構(gòu)中的錯誤需要一個更加通用的方法。企業(yè)應(yīng)用異常框架中最重要的宗旨有:
    ·開發(fā)異常類體系
    ·從系統(tǒng)異常中退耦用戶異常
    ·給出異常的內(nèi)容、類型和嚴(yán)重級別
    ·退耦異常處理和應(yīng)用日志
    ·創(chuàng)建用于異常鏈的工具
    ·具體化用于國際化用途的異常字符串

    許多文章和關(guān)于這個問題的完整書籍,都討論了使用Java的異常處理。Brian Goetz,在他的JavaWorld 系列 "Exceptional Practices" 中提供了關(guān)于這個主題的非常好的建議。

    九、測試,就是用戶想要的!

    盡管許多開發(fā)者都把測試看作是軟件開發(fā)的最不吸引人的部分,測試企業(yè)應(yīng)用對于它的整體成功還是很關(guān)鍵的。許多靈活的方法,如極限程序設(shè)計(XP),將測試放在企業(yè)應(yīng)用開發(fā)的最前部。這種強(qiáng)調(diào)實際上是相當(dāng)爽的。為了簡潔起便,我們只討論用于Struts 類的單元和集成測試策略。

    兩個原始策略可用于服務(wù)器端的測試:模擬對象(MO)測試和容器內(nèi)(IC)測試。模擬對象測試從本質(zhì)上擴(kuò)展了"多樹樁的"行為,并且它是自我說明的。從本質(zhì)上說,開發(fā)者負(fù)責(zé)模擬定義接口的類,這些接口歸進(jìn)行測試的類使用。使用這個方法,開發(fā)者可以模擬容器。模擬對象測試也被叫做endotesting ,因為設(shè)置測試的動作是在受限環(huán)境中的類的內(nèi)部進(jìn)行的。

    容器內(nèi)測試這個策略應(yīng)用于下列情況:在產(chǎn)品環(huán)境中將要使用的實際容器也用于整個單元測試過程中。這些測試案例必須至少合并到使用Ant的每夜建立過程中。單元測試Java類的有效方法之一就是使用JUnit。他是用來測試普通JavaBeans 的一件極好的工具。另外一個重要的開源工具就是Cactus。Cactus,JUnit框架的擴(kuò)展,可以在單元級別上測試服務(wù)器端的代碼。Cactus 支持用于服務(wù)器端測試的容器內(nèi)方法。這兩個測試工具都是很有用的,它是任何追求品質(zhì)的企業(yè)應(yīng)用開發(fā)團(tuán)隊的基石。

    對于測試Struts來說,普遍接受的策略就是通過應(yīng)用層測試演示層。你選擇模擬對象測試方法還是容器內(nèi)測試方法,主要取決于你們團(tuán)隊的需要和安慰級別。要自動執(zhí)行Struts 測試,需要創(chuàng)建一個名為StrutsTestCase 的、對于JUnit測試方法的擴(kuò)展,它對MO 和 IC都支持。使用StrutsTestCase 測試Action 和ActionForm 類,是整個測試策略的一部分,它應(yīng)該包括這里討論的回歸測試工具。其他工具如Apache JMeter 提供了應(yīng)力/負(fù)載測試。

    十、簡化Struts 開發(fā)

    總的來說,我們討論了你應(yīng)該如何簡化struts-config.xml文件的設(shè)計和維護(hù),定義了錯誤處理和測試策略,簡化了常見問題如處理Web瀏覽器的Back按鈕,基于會話期的表格管理以及用戶認(rèn)證。最后,我們還清楚的文檔化了用戶界面控制流程的管理。我們的經(jīng)歷告訴我們:開發(fā)高品質(zhì)的企業(yè)應(yīng)用是困難的。當(dāng)你使用Struts框架創(chuàng)建企業(yè)應(yīng)用時,融合我們的建議到你的開發(fā)計劃中,你就能夠使你的設(shè)計、開發(fā)和維護(hù)費用減至最低。

    關(guān)于作者 Michael Coen 是AgilQuest Corporation的軟件結(jié)構(gòu)師。在AgilQuest時, Mike成為了OnBoard的基于J2EE的企業(yè)軟件應(yīng)用程序開發(fā)團(tuán)隊中的一員。Mike 從事專業(yè)軟件開發(fā)已有11年多。

    Amarnath Nanduri 是AgilQuest Corporation的資深軟件開發(fā)工程師。 Amar在過去六年內(nèi)一直從事企業(yè)軟件應(yīng)用程序的設(shè)計和開發(fā),特別是在用戶界面設(shè)計和開發(fā)方面。Amar 使用Struts框架進(jìn)行開發(fā)已有兩年。

    posted on 2005-10-24 22:13 Sung 閱讀(226) 評論(0)  編輯  收藏 所屬分類: Struts
    主站蜘蛛池模板: 久久九九久精品国产免费直播| 亚洲精品视频在线免费| 亚洲国产精品无码久久SM| 亚洲黄色免费观看| 国产亚洲视频在线观看网址 | 成人AV免费网址在线观看| 亚洲人成网站在线播放2019| 亚洲熟伦熟女新五十路熟妇| 美女内射毛片在线看免费人动物| 亚洲av成人一区二区三区观看在线| 国产偷国产偷亚洲清高动态图| 国产精品免费观看| 亚欧国产一级在线免费| 亚洲a视频在线观看| 在线观看午夜亚洲一区| 毛片A级毛片免费播放| 国产一级婬片A视频免费观看| 丁香婷婷亚洲六月综合色| 精品国产亚洲男女在线线电影 | 亚洲日韩精品国产一区二区三区| 亚洲中文字幕无码爆乳av中文 | 国产91色综合久久免费分享| 免费人成再在线观看网站| 亚洲字幕在线观看| 亚洲精品少妇30p| 国产成人青青热久免费精品| 污污网站免费观看| 国产久爱免费精品视频| 亚洲s码欧洲m码吹潮| 67pao强力打造67194在线午夜亚洲 | 亚洲黄页网在线观看| 亚洲短视频男人的影院| 亚洲中久无码不卡永久在线观看| 四虎在线免费播放| free哆啪啪免费永久| 在线免费观看h片| 视频免费1区二区三区| 亚洲欧美日韩综合久久久久| 亚洲理论片中文字幕电影| 亚洲成A人片在线观看无码不卡| 免费国产一级特黄久久|