happyfish

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            38 Posts :: 1 Stories :: 62 Comments :: 0 Trackbacks

          使用open source產(chǎn)品組裝你的web應(yīng)用架構(gòu)   

          轉(zhuǎn)載自:www.csdn.net


          其實,就算用Java建造一個不是很煩瑣的web應(yīng)用,也不是件輕松的事情。 在構(gòu)架的一開始就有很多事情要考慮。 從高處看,擺在開發(fā)者面前有很多問題:要考慮是怎樣建立用戶接口?在哪里處理業(yè)務(wù)邏輯? 怎樣持久化的數(shù)據(jù)。 而這三層構(gòu)架中,每一層都有他們要仔細考慮的。 各個層該使用什么技術(shù)? 怎樣的設(shè)計能松散耦合還能靈活改變? 怎樣替換某個層而不影響整體構(gòu)架?應(yīng)用程序如何做各種級別的業(yè)務(wù)處理(比如事務(wù)處理)?

           

          構(gòu)架一個Web應(yīng)用需要弄明白好多問題。 幸運的是,已經(jīng)有不少開發(fā)者已經(jīng)遇到過這類問題,并且建立了處理這類問題的框架。 一個好框架具備以下幾點: 減輕開發(fā)者處理復(fù)雜的問題的負擔(dān)(“不重復(fù)發(fā)明輪子”); 內(nèi)部有良好的擴展; 并且有一個支持它的強大的用戶團體。  好的構(gòu)架一般有針對性的處理某一類問題,并且能將它做好(Do One Thing well)。 然而,你的程序中有幾個層可能需要使用特定的框架,已經(jīng)完成的UI(用戶接口) 并不代表你也可以把你的業(yè)務(wù)邏輯和持久邏輯偶合到你的UI部分。  舉個例子, 你不該在一個Controller(控制器)里面寫JDBC代碼作為你的業(yè)務(wù)邏輯, 這不是控制器應(yīng)該提供的。  一個UI 控制器應(yīng)該委派給其它給在UI范圍之外的輕量級組件。 好的框架應(yīng)該能指導(dǎo)代碼如何分布。 更重要的是,框架能把開發(fā)者從編碼中解放出來,使他們能專心于應(yīng)用程序的邏輯(這對客戶來說很重要)。

           

          這篇文章將討論怎樣結(jié)合幾種著名的框架來使得你的應(yīng)用程序做到松弛耦合。

          如何建立你的架構(gòu),并且怎樣讓你的各個應(yīng)用層保持一致。?如何整合框架以便讓每個層在以一種松散偶合的方式彼此作用而不用管低層的技術(shù)細節(jié)?這對我們來說真是一種挑戰(zhàn)。  這里討論一個整合框架的策略( 使用3 種受歡迎的開源框架)  :表示層我們用Struts 業(yè)務(wù)層我們用Spring;而持久層則用Hibernate 你也可以用其他FrameWork替換只要能得到同樣的效果。 見圖1 (框架組合示意圖)

           

          應(yīng)用程序的分層

          大部分的Web應(yīng)用在職責(zé)上至少能被分成4層。 這四層是:presentation(描述),persistence(持久),business(業(yè)務(wù))和domain model(域模塊)。每個層在處理程序上都應(yīng)該有一項明確的責(zé)任, 而不應(yīng)該在功能上與其它層混合,并且每個層要與其它層分開的,但要給他們之間放一個通信接口。   我們就從介紹各個層開始,討論一下這些層應(yīng)該提供什么,不應(yīng)該提供什么。

           

          表示層(The Presentation Layer)

          一般來講,一個典型的Web應(yīng)用的的末端應(yīng)該是表示層。 很多Java發(fā)者也理解Struts所提供的。 象業(yè)務(wù)邏輯之類的被打包到org.apache.struts.Action. 因此,我們很贊成使用Struts這樣的框架。

           

          下面是Struts所負責(zé)的:

               *  管理用戶的請求,做出相應(yīng)的響應(yīng)。

               *  提供一個Controller ,委派調(diào)用業(yè)務(wù)邏輯和其它上層處理。

               *  處理異常,拋給Struts Action

               *  為顯示提供一個模型

               *  UI驗證。 

           

          以下條款,不該在Struts顯示層的編碼中經(jīng)常出現(xiàn)。 它們與顯示層無關(guān)的。

               * 直接的與數(shù)據(jù)庫通信,例如JDBC調(diào)用。

               * 與你應(yīng)用程序相關(guān)聯(lián)的業(yè)務(wù)邏輯以及校驗。

               * 事物管理。

          在表示層引入這些代碼,則會帶來高偶合和麻煩的維護。

           

           

          持久層(The Persistence Layer)

          典型的Web應(yīng)用的另一個末端是持久層。這里通常是程序最容易失控的地方。開發(fā)者總是低估構(gòu)建他們自己的持久框架的挑戰(zhàn)性。系統(tǒng)內(nèi)部的持續(xù)層不但需要大量調(diào)試時間,而且還經(jīng)常缺少功能使之變得難以控制,這是持久層的通病。 還好有幾個ORM開源框架很好的解決了這類問題。尤其是Hibernate Hibernatejava提供了OR持久化機制和查詢服務(wù), 它還給已經(jīng)熟悉SQLJDBC API Java開發(fā)者一個學(xué)習(xí)橋梁,他們學(xué)習(xí)起來很方便。 Hibernate的持久對象是基于POJOJava collections。此外,使用Hibernate并不妨礙你正在使用的IDE

           

          請看下面的條目,你在持久層編碼中需要了解的。

          *  查詢對象的相關(guān)信息的語句。 Hibernate通過一個OO查詢語言(HQL)或者正則表達的API來完成查詢。  HQL非常類似于SQL-- 只是把SQL里的tablecolumnsObject和它的fields代替。 你需要學(xué)習(xí)一些新的HQL語言; 不管怎樣,他們?nèi)菀桌斫舛臋n也做的很好。 HQL是一種對象查詢的自然語言,花很小的代價就能學(xué)習(xí)它。

          *  如何存儲,更新,刪除數(shù)據(jù)庫記錄。

          *  Hibernate這類的高級ORM框架支持大部分主流數(shù)據(jù)庫,并且他們支持 Parent/child關(guān)系,事物處理,繼承和多態(tài)。

           

          業(yè)務(wù)層(The Business Layer

               一個典型Web應(yīng)用的中間部分是業(yè)務(wù)層或者服務(wù)層。 從編碼的視角來看,這層是最容易被忽視的一層。 而我們卻往往在UI層或持久層周圍看到這些業(yè)務(wù)處理的代碼,這其實是不正確的,因為它導(dǎo)致了程序代碼的緊密偶合,這樣一來,隨著時間推移這些代碼很難維護。幸好,針對這一問題有好幾種Frameworks存在。 最受歡迎的兩個框架是SpringPicoContainer 這些為也被稱為microcontainers,他們能讓你很好的把對象搭配起來。 這兩個框架都著手于‘依賴注射’(dependency injection)(還有我們知道的‘控制反轉(zhuǎn)’Inversion of Control=IoC)這樣的簡單概念。 這篇文章將關(guān)注于Spring的注射(譯注:通過一個給定參數(shù)的Setter方法來構(gòu)造Bean,有所不同于Factory, Spring還提供了Setter Injection(type2)Constructor Injection(type3)等方式供我們選擇。  Spring把程序中所涉及到包含業(yè)務(wù)邏輯和DaoObjects——例如transaction management handler(事物管理控制)、Object Factoris(對象工廠)service objects(服務(wù)組件)——都通過XML來配置聯(lián)系起來。

           

          后面我們會舉個例子來揭示一下Spring 是怎樣運用這些概念。 

          業(yè)務(wù)層所負責(zé)的如下:

          * 處理應(yīng)用程序的 業(yè)務(wù)邏輯和業(yè)務(wù)校驗

          * 管理事物

          * 允許與其它層相互作用的接口

          * 管理業(yè)務(wù)層級別的對象的依賴。

          * 在顯示層和持久層之間增加了一個靈活的機制,使得他們不直接的聯(lián)系在一起。

          * 通過揭示 從顯示層到業(yè)務(wù)層之間的Context來得到business services

          * 管理程序的執(zhí)行(從業(yè)務(wù)層到持久層)。

           

           

          域模塊層(The Domain Model Layer

          既然我們致力于的是一個不是很復(fù)雜的Web的應(yīng)用, 我們需要一個對象集合,讓它在不同層之間移動的。  域模塊層由實際需求中的業(yè)務(wù)對象組成 比如, OrderLineItem , Product等等。 開發(fā)者在這層 不用管那些DTOs,僅關(guān)注domain object即可。 例如,Hibernate允許你將數(shù)據(jù)庫中的信息存放入對象(domain objects),這樣你可以在連接斷開的情況下把這些數(shù)據(jù)顯示到UI層。 而那些對象也可以返回給持續(xù)層,從而在數(shù)據(jù)庫里更新。 而且,你不必把對象轉(zhuǎn)化成DTOs(這可能似的它在不同層之間的在傳輸過程中丟失),這個模型使得Java開發(fā)者能很自然運用OO,而不需要附加的編碼。

          一個簡單例子

           

          既然我們已經(jīng)從全局上理解這些組件。 現(xiàn)在就讓我們開始實踐吧。 我們還是用 StrutsSpring Hibernate。這三個框架已經(jīng)被描述夠多了,這里就不重復(fù)介紹了。 這篇文章舉例指導(dǎo)你如何使用這三個框架整合開發(fā),向你揭示 一個請求是如何貫穿于各個層的。(從用戶的加入一個Order到數(shù)據(jù)庫,顯示;進而更新、刪除)。

           

          從這里可以下載到程序程序原代碼(download

           

          既然每個層是互相作用的,我們就先來創(chuàng)建domain objects首先,我們要在這些Object中要確定那些是需要持久化的,哪些是提供給business logic,那些是顯示接口的設(shè)計。  下一步,我們將配置我們的持久層并且定義好HibernateOR mappings。然后定義好Business Objects。有了這些組成部分之后,我們將 使用Spring把這些連接起來。 最后,我們提供給Spring一個持久層,從這個持久層里我們可以知道它是如何與業(yè)務(wù)邏輯層(business service layer)通信的,以及它是怎樣處理其他層拋出的異常的。。

           

          域?qū)ο髮樱?/SPAN>Domain Object Layer

           

          這層是編碼的著手點,我們的編碼就從這層開始。 例子中Order OrderItem 是一個OneToMany的關(guān)系。 下面就是Domain Object Layer的兩個對象:

           

          ·     com.meagle.bo.Order.java: 包含了一個Order的概要信息

          ·     com.meagle.bo.OrderLineItem.java: 包含了Order的詳細信息

          好好考慮怎你的package命名,這反應(yīng)出了你是怎樣分層的。 例如 domain objects在程序中可能打包在com.meagle.bo內(nèi)。  更詳細一點將打包在com. meagle.bo的子目錄下面。business logic應(yīng)該從com.meagle.serice開始打包,而DAO 對象應(yīng)該位于com.meagle.service.dao.hibernate。反應(yīng)FormsActions 持久對象(presentation classes) 應(yīng)該分別放在 com.meagle.actioncom.meagle.forms包。 準(zhǔn)確的給包命名使得你的classes很好分割并且易于維護,并且在你添加新的classes時,能使得程序結(jié)構(gòu)上保持上下一致。

          持久層的配置(Persistence Layer Configuration

          建立Hibernate的持久層 需要好幾個步驟。 第一步讓我們把BO持久化。 既然Hibernate是通過POJO工作的, 因此Order OrderLineItem對象需要給所有的fileds 加上getter,setter方法。 Hibernate通過XML文件來映射(OR)對象,以下兩個xml文件分別映射了Order OrderItem對象。(這里有個叫XDoclet工具可以自動生成你的XML影射文件)

          • Order.hbm.xml
          • OrderLineItem.hbm.xml

          你可以在WebContent/WEB-INF/classes/com/meagle/bo目錄下找到這些xml文件。Hibernate SessionFactory 是用來告訴程序 應(yīng)該與哪個數(shù)據(jù)庫通信,該使用哪個連接池或使用了DataSource 應(yīng)該加載哪些持久對象。而Session接口是用來完成SelectingSavingDeleteUpdating這些操作。 后面的我們將講述SessionFactorySession是怎樣設(shè)置的。

           

          業(yè)務(wù)層的配置(Business Layer Configuration

           

          既然我們已經(jīng)有了domain objects,接下來我們就要business service objects了,用他們來執(zhí)行程序的logic,調(diào)用持久層,得到UI層的requests,處理transactions,并且控制exceptions 為了將這些連接起來并且易于管理,我們將使用面向方面的 SpringFramework Spring 提供了 控制倒置(inversion of control 0==IoC)和注射依賴設(shè)置(setter dependency injection)這些方式(可供選擇),用XML文件將對象連接起來。 IoC是一個簡單概念(它允許一個對象在上層接受其他對象的創(chuàng)建),用IoC這種方式讓你的對象從創(chuàng)建中釋放了出來,降低了偶合度。

           

           

          這里是一個沒有使用IoC的對象創(chuàng)建的例子,它有很高偶合度。

          2.沒有使用 IoC.    A 創(chuàng)建了 B C

           

          而這里是一個使用IoC的例子,這種方式允許對象在高層可以創(chuàng)建并進入另外一個對象,所以這樣可以直接被執(zhí)行。

          3. 對象使用了 IoC A 包含了接受B,C setter方法 , 這同樣達到了 A創(chuàng)建B,C的目的。

           

           

          建立我們的業(yè)務(wù)服務(wù)對象(Building Our Business Service Objects

           

          Business Object中的Setter方法接受的是接口,這樣我們可以很松散的定義對象實現(xiàn),然后注入。 在我們的案例中,我們將用一個business service object接收一個DAO,用它來控制domain objects的持久化。  由于在這個例子中使用了Hibernate,我們可以很方便的用其他持久框架實現(xiàn) 同時通知Spring 有新的DAO可以使用了。

          在面向接口的編程中,你會明白 “注射依賴”模式是怎樣松散耦合你的業(yè)務(wù)邏輯和持久機制的:)。

           

          下面是一個接口business service objectDAO代碼片段:

           

          public interface IOrderService {

            public abstract Order saveNewOrder(Order order)

              throws OrderException,

                     OrderMinimumAmountException;

           

            public abstract List findOrderByUser(

                                               String user)

                                     throws OrderException;

           

            public abstract Order findOrderById(int id)

                                     throws OrderException;

           

            public abstract void setOrderDAO(

                                       IOrderDAO orderDAO);

          }

           

          注意到這段代碼里有一個 setOrderDao(),它就是一個DAO Object設(shè)置方法(注射器)。 但這里并沒有一個getOrderDao的方法,這不必要,因為你并不會在外部訪問這個orderDao。這個DAO Objecte將被調(diào)用,和我們的persistence layer 通信。我們將用SpringDAO Object business service object搭配起來的。因為我們是面向接口編程的,所以并不需要將實現(xiàn)類緊密的耦合在一起。

           

          接下去我們開始我們的DAO的實現(xiàn)類進行編碼。 既然Spring已經(jīng)有對Hibernate的支持,那這個例子就直接繼承HibernateDaoSupport類了,這個類很有用,我們可以參考HibernateTemplate(它主要是針對HibernateDaoSupport的一個用法,譯注:具體可以查看Srping API)。 下面是這個DAO接口代碼:

           

           

          public interface IOrderDAO {
            public abstract Order findOrderById(
                                              final int id);
           
            public abstract List findOrdersPlaceByUser(
                                     final String placedBy);
            public abstract Order saveOrder(
                                         final Order order);
          }

          我們?nèi)匀灰o我們持久層組裝很多關(guān)聯(lián)的對象,這里包含了HibernateSessionFactory TransactionManager Spring 提供了一個  HibernateTransactionManager,他用線程捆綁了一個Hibernate Session,用它來支持transactions(請查看ThreadLocal)

          下面是HibernateSessionFactory   HibernateTransactionManager:的配置:

          <bean id="mySessionFactory"
                 class="org.springframework.orm.hibernate.
                        LocalSessionFactoryBean">
            <property name="mappingResources">
              <list>
                <value>
                  com/meagle/bo/Order.hbm.xml
                </value>
                <value>
                  com/meagle/bo/OrderLineItem.hbm.xml
                </value>
              </list>
            </property>
            <property name="hibernateProperties">
              <props>
                <prop key="hibernate.dialect">
                  net.sf.hibernate.dialect.MySQLDialect
                </prop>
                <prop key="hibernate.show_sql">
                  false
                </prop>
                <prop key="hibernate.proxool.xml">
                  C:/MyWebApps/.../WEB-INF/proxool.xml
                </prop>
                <prop key="hibernate.proxool.pool_alias">
                    spring
                </prop>
              </props>
            </property>
          </bean>
           
          <!-- Transaction manager for a single Hibernate
          SessionFactory (alternative to JTA) -->
          <bean id="myTransactionManager"
                   class="org.
                          springframework.
                          orm.
                          hibernate.
                          HibernateTransactionManager">
            <property name="sessionFactory">
              <ref local="mySessionFactory"/>
            </property>
            </bean>
           

          可以看出:每個對象都可以在Spring 配置信息中用<bean>標(biāo)簽引用。在這里,mySessionFactory引用了HibernateSessionFactory,而myTransactionManager引用了HibernateTransactionManage  注意代碼中myTransactionManger Bean有個sessionFactory屬性。  HibernateTransactionManager有個sessionFactory setter getter方法,這是用來在Spring啟動的時候?qū)崿F(xiàn)“依賴注入” dependency injection)的。  sessionFactory 屬性里 引用mySessionFactory。這兩個對象在Spring容器初始化后就被組裝了起來了。 這樣的搭配讓你從 單例(singleton objects)和工廠(factories)中解放了出來,降低了代碼的維護代價。 mySessionFactory.的兩個屬性,分別是用來注入mappingResources hibernatePropertes的。通常,如果你在Spring之外使用Hibernate,這樣的設(shè)置應(yīng)該放在hibernate.cfg.xml中的。 不管怎樣,Spring提供了一個便捷的方式-----Spring內(nèi)部配置中并入了Hibernate的配置。 如果要得到更多的信息,可以查閱Spring API

           

           

          既然我們已經(jīng)組裝配置好了Service Beans,就需要把Business Service Object DAO也組裝起來,并把這些對象配到一個事務(wù)管理器(transaction manager)里。

           

          Spring中的配置信息:

          <!-- ORDER SERVICE -->
          <bean id="orderService"
            class="org.
                   springframework.
                   transaction.
                   interceptor.
                   TransactionProxyFactoryBean">
            <property name="transactionManager">
              <ref local="myTransactionManager"/>
            </property>
            <property name="target">
              <ref local="orderTarget"/>
            </property>
            <property name="transactionAttributes">
              <props>
                <prop key="find*">
               PROPAGATION_REQUIRED,readOnly,-OrderException
                </prop>
                <prop key="save*">
               PROPAGATION_REQUIRED,-OrderException
                </prop>
              </props>
            </property>
          </bean>
           
          <!-- ORDER TARGET PRIMARY BUSINESS OBJECT:
          Hibernate implementation -->
          <bean id="orderTarget"
                   class="com.
                          meagle.
                          service.
                          spring.
                          OrderServiceSpringImpl">
            <property name="orderDAO">
              <ref local="orderDAO"/>
            </property>
          </bean>
           
          <!-- ORDER DAO OBJECT -->
          <bean id="orderDAO"
                   class="com.
                          meagle.
                          service.
                          dao.
                          hibernate.
                          OrderHibernateDAO">
            <property name="sessionFactory">
              <ref local="mySessionFactory"/>
            </property>
          </bean>

           

           

          4 是我們對象搭建的一個提綱。 從中可以看出,每個對象都聯(lián)系著Spring,并且能通過Spring注入到其他對象。把它與Spring的配置文件比較,觀察他們之間的關(guān)系

           


          4. Spring就是這樣基于配置文件,將各個Bean搭建在一起。

           

          這個例子使用一個TransactionProxyFactoryBean,它定義了一個setTransactionManager() 這對象很有用,他能很方便的處理你申明的事物還有Service Object    你可以通過transactionAttributes屬性來定義怎樣處理。 想知道更多還是參考TransactionAttributeEditor吧。

          TransactionProxyFactoryBean 還有個setter. 這會被我們 Business service objectorderTarget)引用, orderTarget定義了 業(yè)務(wù)服務(wù)層,并且它還有個屬性,由setOrderDAO()引用。這個屬性

           

          Spring Bean 的還有一點要注意的: bean可以以用兩種方式創(chuàng)造。 這些都在單例模式(Sington)和原型模式(propotype)中定義了。  默認的方式是singleton,這意味著共享的實例將被束縛。 而原形模式是在Spring用到bean的時候允許新建實例的。當(dāng)每個用戶需要得到他們自己Bean的Copy時,你應(yīng)該僅使用prototype模式。(更多的請參考設(shè)計模式中的單例模式和原形模式)

          提供一個服務(wù)定位器(Providing a Service Locator

           

          既然我們已經(jīng)將我們的SericesDAO搭配起來了。我們需要把我們的Service顯示到其他層。 這個通常是在Struts或者Swing這層里編碼。一個簡單方法就是用 服務(wù)定位器返回給Spring context 。當(dāng)然,可以通過直接調(diào)用Spring中的Bean來做。

           

          下面是一個Struts Actin 中的服務(wù)定位器的一個例子。

           

          public abstract class BaseAction extends Action {
           
            private IOrderService orderService;
           
            public void setServlet(ActionServlet
                                           actionServlet) {
              super.setServlet(actionServlet);
              ServletContext servletContext =
                         actionServlet.getServletContext();
           
              WebApplicationContext wac =
                WebApplicationContextUtils.
                   getRequiredWebApplicationContext(
                                           servletContext);
           
                this.orderService = (IOrderService)
                               wac.getBean("orderService");
            }
           
            protected IOrderService getOrderService() {
              return orderService;
            }
          }

           

           

          UI 層配置 UI Layer Configuration

          這個例子里UI層 使用了Struts framework. 這里我們要講述一下在給程序分層的時候, 哪些是和Struts部分的。我們就從一個Struts-config.xml文件中的Action的配置信息開始吧。

          struts-config.xml file.

          <action path="/SaveNewOrder"
              type="com.meagle.action.SaveOrderAction"
              name="OrderForm"
              scope="request"
              validate="true"
              input="/NewOrder.jsp">
            <display-name>Save New Order</display-name>
            <exception key="error.order.save"
              path="/NewOrder.jsp"
              scope="request"
              type="com.meagle.exception.OrderException"/>
            <exception key="error.order.not.enough.money"
              path="/NewOrder.jsp"
              scope="request"
              type="com.
                    meagle.
                    exception.
                    OrderMinimumAmountException"/>
            <forward name="success" path="/ViewOrder.jsp"/>
            <forward name="failure" path="/NewOrder.jsp"/>
          </action>
           

          SaveNewOrder 這個Action是用來持久化UI層里的表單提交過來Order的。這是Struts中一個很典型的Action;  注意觀察這個Actionexception配置,這些Exceptions也在Spring 配置文件(applicationContext-hibernate.xml)配置了(就在 business service object transactionAttributes屬性里)。 當(dāng)異常在業(yè)務(wù)層被被拋出時,我們可以控制他們,并適當(dāng)?shù)娘@示給UI層。 

          第一個異常,OrderException,在持久層保存order對象失敗的時候被觸發(fā)。這將導(dǎo)致事物回滾并且通過BO把異常回傳到Struts這一層。

          第二個異常,OrderMinimumAmountException也同第一個一樣。

           

           

          搭配整和的最后一步 通過是讓你顯示層和業(yè)務(wù)層相結(jié)合。這個已經(jīng)被服務(wù)定位器(service locator)實現(xiàn)了(前面討論過了), 這里服務(wù)層作為一個接口提供給我們的業(yè)務(wù)邏輯和持久層。 

           

          SaveNewOrder Action Struts中用一個服務(wù)定位器(service locator)來調(diào)用執(zhí)行業(yè)務(wù)方法的。 方法代碼如下:

           

          public ActionForward execute(

            ActionMapping mapping,

            ActionForm form,

            javax.servlet.http.HttpServletRequest request,

            javax.servlet.http.HttpServletResponse response)

            throws java.lang.Exception {

           

            OrderForm oForm = (OrderForm) form;

           

            // Use the form to build an Order object that

            // can be saved in the persistence layer.

            // See the full source code in the sample app.

           

            // Obtain the wired business service object

            // from the service locator configuration

            // in BaseAction.

            // Delegate the save to the service layer and

            // further upstream to save the Order object.

            getOrderService().saveNewOrder(order);

           

            oForm.setOrder(order);

           

            ActionMessages messages = new ActionMessages();

            messages.add(

                ActionMessages.GLOBAL_MESSAGE,

                      new ActionMessage(

                "message.order.saved.successfully"));

           

            saveMessages(request, messages);

           

            return mapping.findForward("success");

          }

           

          總結(jié)

                 這篇文章在技術(shù)和構(gòu)架方面掩蓋了很多低層的基礎(chǔ)信息, 文章的主要的意圖在于讓你意識到如何給你應(yīng)用程序分層。  分層可以“解耦”你的代碼——允許新的組件被添加進來,而且讓你的代碼易于維護。  這里用到的技術(shù)只是專注于把“解偶”做好。 不管怎樣,使用這樣的構(gòu)架可以讓你用其他技術(shù)代替現(xiàn)在的層。 例如,你可能不使用Hibernate實現(xiàn)持久化。既然你在DAO中面向接口的編程的,所以你完全可以用iBATIS來代替。或者,你也可能想用Struts外的其他的技術(shù)或者框架替換現(xiàn)在的UI層(轉(zhuǎn)換久層,實現(xiàn)層并不應(yīng)該直接影響到你的業(yè)務(wù)邏輯和業(yè)務(wù)服務(wù)層)。 用適當(dāng)?shù)目蚣艽罱愕?/SPAN>Web應(yīng)用,其實也不是一件煩瑣的工作,更主要的是它“解耦”了你程序中的各個層.

          posted on 2005-03-02 22:38 小魚兒 閱讀(247) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 大同市| 灵宝市| 钟山县| 东兴市| 茂名市| 芜湖县| 宜君县| 太保市| 上杭县| 博爱县| 东阳市| 海门市| 阜阳市| 奈曼旗| 磐安县| 永年县| 万载县| 太仆寺旗| 常山县| 宣武区| 行唐县| 新龙县| 嵊泗县| 宁夏| 石嘴山市| 桑日县| 天台县| 开平市| 西乌| 青岛市| 元朗区| 咸宁市| 中卫市| 万荣县| 成武县| 泸州市| 大足县| 伊宁县| 理塘县| 南溪县| 淅川县|