乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      利用j2ee建站

       軟件團(tuán)隊頭目 2007-08-16

      文檔選項
      將此頁作為電子郵件發(fā)送

      將此頁作為電子郵件發(fā)送


      最新推薦

      Java 應(yīng)用開發(fā)源動力 - 下載免費軟件,快速啟動開發(fā)


      級別: 初級

      李志,

      2003 年 7 月 01 

      本文以一個教學(xué)網(wǎng)站的建設(shè)思路為例,探討利用J2EE技術(shù)和WebSphere產(chǎn)品構(gòu)建網(wǎng)站的模式和方法。

      一、前言

      本文以一個教學(xué)網(wǎng)站的建設(shè)思路為例,探討利用J2EE技術(shù)和WebSphere產(chǎn)品構(gòu)建網(wǎng)站的模式和方法。





      回頁首


      二、設(shè)計網(wǎng)站系統(tǒng)

      我們的樣例是一個教學(xué)網(wǎng)站系統(tǒng),它的軟件包括WebSphere Application Server應(yīng)用服務(wù)器軟件V4.0、WSAD開發(fā)工具和DB2數(shù)據(jù)庫(非商業(yè)用途),硬件為IBM xSeries服務(wù)器。在本文中,主要探討MVC的開發(fā)模型和常用的J2EE模式,關(guān)于網(wǎng)站建設(shè)的其他細(xì)節(jié)就略過不提了。

      (一)系統(tǒng)用例圖

      分析網(wǎng)站的系統(tǒng)目標(biāo)后,我們首先具體化系統(tǒng)功能,形成一張用例圖,定義一系列的可重構(gòu)組件,以指導(dǎo)隨后的開發(fā)工作。


      圖1 Use Case picture
       圖1 Use Case picture

      (二)組件化設(shè)計

      在構(gòu)造網(wǎng)站系統(tǒng)時,我們把每層的系統(tǒng)想象成擁有多個"槽"的裝置,開發(fā)人員可以向槽中插入組件以擴大其能力,也可以通過繼承或其他機制具體化組件系統(tǒng)。這些組件可以是開發(fā)人員為該應(yīng)用系統(tǒng)開發(fā)的,也可以是以前開發(fā)好的復(fù)用組件。在這種分層體系結(jié)構(gòu)中,每個應(yīng)用系統(tǒng)都表示為一個單獨的系統(tǒng)。每個系統(tǒng)都采用組件構(gòu)造。每個組件系統(tǒng)又可以通過其他下層組件系統(tǒng)構(gòu)造。重構(gòu)人員采用一組與特定應(yīng)用系統(tǒng)領(lǐng)域和業(yè)務(wù)有關(guān)的組件或頂層中的組件系統(tǒng)來構(gòu)造每個應(yīng)用系統(tǒng)。

      結(jié)合J2EE,讓我們首先了解J2EE體系中的組件構(gòu)成情況,如圖2所示。


      圖2J2EE組件打包策略
      圖2  J2EE組件打包策略

      在上圖中可以看出,不同的組件歸檔到不同的文件包中,這樣就保證了一個組件的"插拔"不會影響到其它的組件。根據(jù)應(yīng)用系統(tǒng)組件的功能,我們可以把它們分為動態(tài)組件和靜態(tài)組件。靜態(tài)的組件包含網(wǎng)頁文件,主要用于放置教學(xué)資料和參考文章。動態(tài)組件則包括各種功能模塊,如論壇系統(tǒng)、模擬測驗系統(tǒng)等。

      應(yīng)用系統(tǒng)組件之下是于特定業(yè)務(wù)有關(guān)的組件。在這里,我們可以添加非Java編寫的一些程序,用于處理特定內(nèi)容下的操作,比如模擬測驗系統(tǒng)中的出題模塊。當(dāng)然,要考慮到上層組件調(diào)用的正面接口問題。對于這層組件,我們能夠隨時替換,只要其提供的數(shù)據(jù)符合上級正面的要求。

      以上兩級組件之下是J2EE應(yīng)用服務(wù)器和操作系統(tǒng),整體如圖3所示。


      圖3 計算機組成原理網(wǎng)站系統(tǒng)組件架構(gòu)圖
      圖3 計算機組成原理網(wǎng)站系統(tǒng)組件架構(gòu)圖

      (三)利用J2EE模式開發(fā)組件系統(tǒng)

      下面著重介紹開發(fā)過程中使用的J2EE模式,這些模式都是通用類型的。

      本系統(tǒng)采用MVC開發(fā)模型,即Model-View-Controller。Model是指應(yīng)用程序的數(shù)據(jù),以及對這些數(shù)據(jù)的操作;View是指用戶界面;Controller負(fù)責(zé)用戶界面和程序數(shù)據(jù)之間的同步。這種模型的好處在于分離不同功能的代碼,便于以后的維護(hù),還有利于在項目小組內(nèi)按照小組成員各自的擅長進(jìn)行分工,有利于三個部分并行開發(fā)、加快項目進(jìn)度。

      為了使各開發(fā)人員協(xié)調(diào)一致,為其他組件提供一致和標(biāo)準(zhǔn)的正面,增強系統(tǒng)的可維護(hù)性和可復(fù)用性,我們廣泛采用了SUN公司提出的基于MVC的設(shè)計模式。

      圖4是用戶注冊模塊的UML圖,我們將結(jié)合這個模塊具體闡述各模式的特點和在本系統(tǒng)中的實際應(yīng)用。


      圖4 表示層模式
      圖4 表示層模式

      明確了所采用的體系和模式,下面具體設(shè)計類的屬性和方法,通過設(shè)計完善的接口和繼承、重載等方法進(jìn)行重構(gòu)。模塊的UML的類圖表示如下:


      圖5 模塊的UML的類圖
      圖5 模塊的UML的類圖

      結(jié)合上圖,讓我們看看這個模塊中都運用了哪些模式。

      1. 表示層模式

      系統(tǒng)的表示層集中了MVC模式中的View與Controller。該系統(tǒng)用JSP代表View,用Servlet代表Controller。在Controller這一模塊中,又采用了視圖助手、分發(fā)者與值對象模式,以增強系統(tǒng)的模塊化,提高維護(hù)性。

      (1)前端控制器

      控制器通常表現(xiàn)為Servlet形式,其UML表示如下:


      圖6 前端控制器
      圖6 前端控制器

      根據(jù)Model-View-Controller的開發(fā)思想,使用控制器作為處理請求的最初聯(lián)系點。該控制器管理著請求的處理,包括調(diào)用安全服務(wù),比如驗證和授權(quán)、委托業(yè)務(wù)處理、管理合適的視圖選擇、處理錯誤,以及管理內(nèi)容創(chuàng)建邏輯的選擇。也可以把前端控制器看成一個觸發(fā)器,由它來啟動流程。

      下面是功能代碼的樣本。其中出現(xiàn)的RegisterHelper、Command等類,接下來會有詳細(xì)介紹。

      
                                 public void performTask(javax.servlet.http.HttpServletRequest request,
                              javax.servlet.http.HttpServletResponse response)
                              throws javax.servlet.ServletException, java.io.IOException
                              {
                              RegisterHelper rh=new RegisterHelper(request,response);//啟動注冊視圖助手
                              Command command=rh.getCommand();//由視圖助手中獲得并初始化Command
                              CustomerBean cb=rh.getCustomerBean();//由視圖助手中獲得并初始化值對象
                              request.setAttribute("customerbean",cb);
                              String dispatcher=rh.getDispatcher();//由視圖助手中獲得并初始化分發(fā)者
                              request.setAttribute("type",rh.getType());//設(shè)置上下文屬性
                              try {
                              command.execute((Helper)rh);//執(zhí)行業(yè)務(wù)代碼
                              } catch(javax.ejb.DuplicateKeyException de) {
                              request.setAttribute("errorbean",new ErrorBean("對不起,已經(jīng)有人注冊了該用戶名!"));//注冊重名處理
                              dispatch(request,response,dispatcher);//分發(fā)并移交控制權(quán)
                              return;
                              } catch(Exception e) {
                              request.setAttribute("errorbean",new ErrorBean("對不起,數(shù)據(jù)庫出錯!"));//出錯處理
                              dispatch(request,response,dispatcher);
                              return;
                              }
                              dispatch(request,response,dispatcher);
                              }
                              

      優(yōu)點:通過集中化決策點和控制,控制器有助于減少嵌入在JSP中Java代碼(Scriptlet)的數(shù)量,保持View功能的純潔性。它的位置如圖5中Controller所示。

      (2)視圖助手

      表示層更改經(jīng)常發(fā)生,而且當(dāng)業(yè)務(wù)數(shù)據(jù)訪問邏輯和表示格式化邏輯被混雜時,表示層更改很難開發(fā)和維護(hù)。這使系統(tǒng)靈活性更差,更缺乏可用性,而且對變化的適應(yīng)性更弱。


      圖7 視圖助手
      圖7 視圖助手

      視圖包含格式化代碼,把其處理責(zé)任委托給其助手類。助手也存儲該視圖的中間數(shù)據(jù),如表單、URL參數(shù)等,并且充當(dāng)業(yè)務(wù)數(shù)據(jù)適配器。

      下面是功能代碼的樣本。

      
                              public class RegisterHelper implements Helper {
                              static String dispatcher = "RegisterDispatcher";
                              private CustomerBean customer = null;
                              private String type = null;
                              public RegisterHelper(
                              javax.servlet.http.HttpServletRequest request,
                              javax.servlet.http.HttpServletResponse response) {
                              setType(request);
                              setCustomerBean(request);
                              }
                              /**
                              * 定義頁面類型:HTML or XML
                              */
                              public void setType(javax.servlet.http.HttpServletRequest request) {
                              type = request.getParameter("type");
                              }
                              /**
                              * 獲取Command
                              */
                              public Command getCommand() {
                              RegisterCommand rc = new RegisterCommand();
                              return rc;
                              }
                              /**
                              * 向值對象中填充數(shù)據(jù)
                              */
                              public void setCustomerBean(javax.servlet.http.HttpServletRequest request) {
                              customer = new CustomerBean();
                              customer.setUsername(request.getParameter("username"));
                              customer.setPassword(request.getParameter("password"));
                              customer.setEmail(request.getParameter("email"));
                              customer.setTruename(request.getParameter("truename"));
                              customer.setId(request.getParameter("id"));
                              customer.setService(this.setService(request));
                              }
                              /**
                              * 獲取值對象
                              */
                              public CustomerBean getCustomerBean() {
                              return this.customer;
                              }
                              /**
                              * 獲取分發(fā)者
                              */
                              public String getDispatcher() {
                              return this.dispatcher;
                              }
                              /**
                              * 獲取類型
                              */
                              public String getType() {
                              return type;
                              }
                              }
                              

      優(yōu)點:在助手中而不是在視圖中封裝業(yè)務(wù)邏輯會增強應(yīng)用程序的模塊化,并且更有利于組件重用。助手有大量的責(zé)任,包括收集視圖和控制需要的數(shù)據(jù),以及存儲中間模型。它的位置如圖5中Helper所示。

      (3)Command模式

      Command中包含純業(yè)務(wù)代碼,如注冊、登陸、檢驗等。在樣例模塊中,它的職責(zé)是將注冊信息傳遞給Entity Bean。


      圖8 Command
      圖8 Command

      功能代碼如下所示:

      
                                    public void execute(Helper helper) throws Exception
                              {
                              RegisterHelper rh = (RegisterHelper) helper;//獲取視圖助手
                              CustomerBean cb = rh.getCustomerBean();//從視圖助手中獲取值對象
                              ServiceLocator sl = ServiceLocator.getInstance();//初始化服務(wù)定位器
                              CustomersHome ch = (CustomersHome) sl.getHome(ServiceLocator.Services.CUSTOMERS);//從服務(wù)定位器中獲取Entity Bean本地接口
                              try {
                              Customers customers = ch.create(cb);//將注冊信息導(dǎo)入數(shù)據(jù)庫
                              } catch(javax.ejb.DuplicateKeyException e) {
                              throw new javax.ejb.DuplicateKeyException();
                              } catch(Exception e) {
                              throw e;
                              }
                              }
                              

      (4)分發(fā)者模式

      如果將表示化邏輯和業(yè)務(wù)邏輯混合在視圖中,會使系統(tǒng)可重用性和靈活性變差,而且一半還會使更改操作難以實施。分發(fā)者負(fù)責(zé)視圖管理和導(dǎo)航,選擇下一個視圖,并且提供分發(fā)資源控制的機制。分發(fā)者可以提供靜態(tài)的分發(fā),也能提供更高級的動態(tài)分發(fā)機制。

      在我們的項目中,由于涉及到PC用戶和移動手機用戶的訪問,我們需要針對不同的用戶返回不同的結(jié)果頁面,因此分發(fā)者的存在就非常有必要。分發(fā)者表現(xiàn)為Servlet形式,它承接Controller的處理結(jié)果,并判斷用戶的類型,把正確的視圖返回給用戶。它的位置如圖5中Dispatcher所示。


      圖9 分發(fā)者
      圖9 分發(fā)者

      功能代碼如下所示:

      
                                public void performTask(
                              javax.servlet.http.HttpServletRequest request,
                              javax.servlet.http.HttpServletResponse response)
                              throws javax.servlet.ServletException, java.io.IOException {
                              String type=(String)request.getAttribute("type");//獲取頁面類型
                              isError=(request.getAttribute("errorbean")!=null)?true:false;//判斷是否出錯
                              String file=selectType(type,isError,response);//根據(jù)頁面類型和是否出錯確定顯示頁面
                              getServletConfig().getServletContext().getRequestDispatcher(file).forward(request,response);//重定向到顯示頁面
                              }
                              public String selectType(String str,boolean isError,javax.servlet.http.HttpServletResponse response) {
                              if (str.equals("html")) {//HTML類型的頁面
                              if (isError) {//成功
                              System.out.println("Some error happens!");
                              return "register_error.jsp";
                              } else {//出錯    return "register_ok.jsp";
                              }
                              } else {//WML手機頁面
                              if (isError) {//成功
                              System.out.println("Some error happens!");
                              return "wml/register_error.jsp";
                              } else {//出錯
                              response.setContentType("text/vnd.wap.wmlcharset=ISO-8859-1");
                              return "wml/register_ok.jsp";
                              }
                              }
                              }
                              

      (5)復(fù)合視圖

      復(fù)雜的Web頁面可以展示來自多個數(shù)據(jù)源的內(nèi)容,使用多個包含單顯示頁面的子視圖。同時,具有不同技能的多個開發(fā)人員可以參與這些Web頁面的開發(fā)和維護(hù)。

      因此,我們采用有多個原子視圖組成的復(fù)合視圖。模版中每個組件是動態(tài)結(jié)合在一起的,并且頁面的布局是獨立于內(nèi)容進(jìn)行管理的。在我們的項目中,采用了<jsp:include page="***" flush="true">嵌入頁面,使導(dǎo)航欄和標(biāo)示獨立于各個頁面,使用戶能夠及時地看到任何變動,并使系統(tǒng)更改的代價降低到最小。

      2. 業(yè)務(wù)層模式

      (1)值對象

      J2EE應(yīng)用程序把服務(wù)器端業(yè)務(wù)組件實現(xiàn)為Session Bean和Entity Bean。業(yè)務(wù)組件的一些方法可以向客戶端返回數(shù)據(jù)。通常,客戶端需要多次調(diào)用業(yè)務(wù)對象的get/set方法直到獲得所有的屬性值。由于EJB的調(diào)用采用RMI-IIOP方式通過網(wǎng)絡(luò)進(jìn)行,這樣做大大延緩了業(yè)務(wù)層的處理速度,降低了效率。

      為了解決這一問題,我們使用值對象封裝業(yè)務(wù)數(shù)據(jù)。相應(yīng)的方法調(diào)用是設(shè)置和檢索值對象。當(dāng)客戶端向企業(yè)bean請求業(yè)務(wù)數(shù)據(jù)時,該企業(yè)bean可以構(gòu)造值對象,用屬性值來填充,并且按照值把它傳遞給客戶端,這也符合EJB端粗粒度調(diào)用的需要。

      值對象是可串行化的JavaBean對象。值對象類也可以提供接收所有必須的屬性以創(chuàng)建該值對象的構(gòu)造器。通常,值對象中的成員被定義為私有的,而其Get/Set方法則是公有的。


      圖10值對象
      圖10值對象

      如圖10所示,作為示例的CutomerBean中包含了對應(yīng)Entity Bean所需的屬性及其訪問方法。

      (2)服務(wù)定位器

      J2EE客戶端與EJB組件進(jìn)行交互,這些組件提供業(yè)務(wù)服務(wù)和持久性能力。為了與它們交互,客戶端必須定位(或稱為查找)該服務(wù)組件,或創(chuàng)建一個新的組件。比如,EJB客戶端必須定位EJB的本地對象,然后客戶端使用該本地對象來查找某對象,或者創(chuàng)建或刪除一個或多個EJB。

      這樣,對于所有需要訪問JNDI管理的服務(wù)對象的客戶端而言,都需要進(jìn)行定位工作。在需要查找服務(wù)的客戶端中,會導(dǎo)致不必要的代碼重復(fù)現(xiàn)象。同時,創(chuàng)建最初JNDI環(huán)境和在EJB本地對象上執(zhí)行查找都會占用大量的資源。如果多個客戶端反復(fù)地請求相同的bean本地對象,這種重復(fù)現(xiàn)象會嚴(yán)重影響應(yīng)用程序性能。

      我們使用服務(wù)定位器對象來抽取所有的JNDI應(yīng)用,并且隱蔽最初環(huán)境創(chuàng)建、EJB本地對象查找和EJB對象重創(chuàng)建的復(fù)雜性。多個客戶端可以重新使用服務(wù)定位器對象來降低代碼的復(fù)雜性,提供單控制點,并且通過提供緩沖機制來提高性能。

      該模式降低了來自于客戶端依賴性的客戶端復(fù)雜性,并且需要執(zhí)行查找和創(chuàng)建過程,這些都是非常消耗資源的。為了消除這些問題,該模式提供了把所有依賴性和網(wǎng)絡(luò)細(xì)節(jié)抽取到服務(wù)定位器的一種機制。它的位置如圖11中ServiceLocator所示。


      圖11 服務(wù)定位器
      圖11 服務(wù)定位器

      功能代碼如下所示:

      
                              public class ServiceLocator
                              {
                              private static ServiceLocator me;
                              InitialContext context = null;
                              /**
                              * 初始化上下文
                              */
                              public ServiceLocator()
                              {
                              try {
                              context = new InitialContext();
                              } catch (NamingException e) {
                              e.printStackTrace();
                              }
                              }
                              public class Services {
                              //為EJB設(shè)定請求序號
                              final public static int CUSTOMERS=0;
                              final public static int PARTNERS=1;
                              final public static int ADMINISTRATORS=2;
                              final public static int PERMITS=3;
                              final public static int PAPERBROKER=4;
                              final public static int CHECK=5;
                              }
                              final static Class CUSTOMERS_CLASS=CustomersHome.class;
                              final static String CUSTOMERS_NAME="CustomersHome";
                              final static Class PARTNERS_CLASS=PartnersHome.class;
                              final static String PARTNERS_NAME="PartnersHome";
                              final static Class ADMINISTRATORS_CLASS=AdministratorsHome.class;
                              final static String ADMINISTRATORS_NAME="AdministratorsHome";
                              final static Class PERMITS_CLASS=PermitsHome.class;
                              final static String PERMITS_NAME="PermitsHome";
                              final static Class PAPERBROKER_CLASS=PaperBrokerHome.class;
                              final static String PAPERBROKER_NAME="PaperBrokerHome";
                              final static Class CHECK_CLASS=CheckHome.class;
                              final static String CHECK_NAME="CheckHome";
                              public static ServiceLocator getInstance() {//單線程處理以節(jié)省資源
                              if (me == null)
                              me = new ServiceLocator();
                              return me;
                              }
                              static private Class getServiceClass(int service) {
                              switch(service) {
                              case Services.CUSTOMERS:
                              return CUSTOMERS_CLASS;
                              case Services.PARTNERS:
                              return PARTNERS_CLASS;
                              case Services.ADMINISTRATORS:
                              return ADMINISTRATORS_CLASS;
                              case Services.PERMITS:
                              return PERMITS_CLASS;
                              case Services.PAPERBROKER:
                              return PAPERBROKER_CLASS;
                              case Services.CHECK:
                              return CHECK_CLASS;
                              }
                              return null;
                              }
                              static private String getServiceName(int service) {
                              switch(service) {
                              case Services.CUSTOMERS:
                              return CUSTOMERS_NAME;
                              case Services.PARTNERS:
                              return PARTNERS_NAME;
                              case Services.ADMINISTRATORS:
                              return ADMINISTRATORS_NAME;
                              case Services.PERMITS:
                              return PERMITS_NAME;
                              case Services.PAPERBROKER:
                              return PAPERBROKER_NAME;
                              case Services.CHECK:
                              return CHECK_NAME;
                              }
                              return null;
                              }
                              /**
                              * 返回EJB本地接口
                              */
                              public EJBHome getHome(int s)
                              {
                              EJBHome home = null;
                              try {
                              Object objref = context.lookup(getServiceName(s));
                              home = (EJBHome) PortableRemoteObject.narrow(objref, getServiceClass(s));
                              } catch (NamingException e) {
                              e.printStackTrace();
                              }
                              return home;
                              }
                              }
                              

      缺點:如果增加新的EJB,需要修改服務(wù)定位器的代碼。

      以上這些模式都是可以通用的,在實際應(yīng)用中運用這些模式,不僅加快了開發(fā)進(jìn)度,而且開發(fā)人員各司其職,避免了代碼的混亂,取得了比較好的效果。





      回頁首


      三、總結(jié)

      本文記述了根據(jù)J2EE模式和MVC開發(fā)模型,利用IBM公司的WebSp here應(yīng)用服務(wù)器來組織建設(shè)網(wǎng)站的心得和體會。大家的項目類型也許會有不同,但開發(fā)的模式總會有相通之處。善于根據(jù)實際情況選擇開發(fā)模式,可以提高開發(fā)效率和代碼質(zhì)量,但也不要一味死抱著模式不放,量體裁衣才能游刃有余。


        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多