前一版本 |
|
修定日期 |
2004-3 |
版本號碼 |
1.0 |
修定人 |
楊才高 |
J2EE 軟體開發過程 詳 解 與 心 得 深圳桑達資訊技術有限公司 2004-03 目 錄 第 1 部份 寫在前面 第 2 部份 需求分析 第 3 部份 系統設計 § 3.1 使用案例圖 § 3.2 類圖 § 3.3 元件圖表 第 4 部份 系統實現 § 4.1 簡述 § 4.2 基本代碼 § 4.3 源碼分析 § 4.4 WEB實現 第 5 部份 程式開發 第 6 部份 深化 ---- 一個實用的工程 第 7 部份 與我聯絡 • 寫在前面 有感於 J2EE 的強大功能,我在學習 java 語言的過程中,逐步掌握了大量的實用技術,想找一個項目來完成自己的功能,於是就有了這份文檔。 本文的寫作思路體現了我的學習曆程,也記錄了作者的 java 學習經曆,同時也有深刻的體會。 在開始本項目之前,需要掌握的技術包括: 物件導向的基礎知識 java 語言 ant 的基礎知識,簡單使用方法 jsp 的基本知識及其簡單用法 servlet 程式的寫法 ejb 程式的結構 文就兩個項目作了闡述,第一個是關於員工和部門的描述,第二個是實用資料庫查詢。 • 需求分析 這個項目目的很簡單,就是通過本項目的實現,學習 J2EE/JEB 在 JBOSS 中的實現,同時加深理解相關技術並能加以應用。 本項目要求實現部門和員工及他們之間的關係,部門與部門之間的關係。 要求: 部門的刪除,增加操作 一個部門可以是最上層部門,也可以是另一個已存在部門的子部門 一個部門的子部門是不需要限制的,可以任意多層子部門 員工的增加,列表操作 員工是從屬於某一部門的 員工顯示是需要分頁的 需要使用某種形式將這些功能顯示出來 • 系統設計 針對以上分析,可以認為這裡面有兩個實體,一個是部門( Department ),另一個是員工( Employee ),這裡可以將這兩個實體設計為實體 BEAN ,並通過容器來管理,即 J2EE 裡面的 CMP EJB 。根據分析,這兩個實休由以下欄位組成: Department Id 部門的 ID, 通常可以自動產生,但由於我們在父類別識別碼 中需要用到它,因此這裡我們在程式中手動產生 (MaxID+1) 。 Name 部門的名稱 Detail 部門的描述 Parentid 父類別識別碼 為 ID 的引用 Employee UserId 員工 ID 可以是數字 ID ,也可以是英文 ID RealName 員工真實姓名 NickName 暱稱 IDCard 社會安全號碼 Birthday 出生日期 Email 電子郵件地址 DepartmentID 所在部門 ID Department 實體的外部參考 • 使用案例圖 • 類圖 這裡只顯示了兩個最基本的類: EJB 實體 BEAN 類,由這兩個類可以產生 Interfaces, Data, Util 包中的一共八個類。另外兩個需要手動完成的輔助 Fa?ade 模式類可以自動產生 Interfaces,fa?ade 包中的六個類。 更詳細的類圖設計由其他工具產生,這裡不便畫出。 • 元件圖表 • 系統實現 • 簡述 該項目採用 eclipse 開發,運行於 jboss/tomcat 3.23 上,運行效果良好。 系統基本上遵循了 MVC 的軟體設計模式,體現在兩個方面,一個是 EJB 部份,一個是 WEB 顯示部份。 EJB 部份採用了 Xdoclet 方式實現代碼自動產生,因此代碼量很小,只需要實現幾個關鍵類,其他輔助類都由系統自動產生,這樣做提高了效率和生產力,也是 MVC 原理的具體體現,結構非常清晰,資料庫處理也自動完成。 WEB 部門由於採用了 STRUTS 構架,是 MVC 模式在 WEB 應用程式上的最佳代表。 Data 包中的資料是模型, jsp 頁面是視圖, action servlet 是控制器。 具體實現代碼清單如下: ibm.cmpr.DepartmentBean.java • 基本代碼 /* * $Id: DepartmentBean.java,v 1.1 2004/03/25 00:54:03 wadmin Exp $ * @author 楊才高 * @version $Revision: 1.1 $ */package ibm.ejb;import java.rmi.RemoteException;import java.util.Collection;import javax.ejb.EJBException;import javax.ejb.EntityBean;import javax.ejb.EntityContext;import javax.ejb.RemoveException;/** * @ejb.bean * cmp-version="2.x" * local-jndi-name="DepartmentHomeLocal" * name="Department" * primkey-field="id" * type="CMP" * view-type="local" * @ejb.finder * method-intf="LocalHome" * query="SELECT OBJECT(o) FROM Phone o" * result-type-mapping="Local" * signature="java.util.Collection findAll()" * @ejb.persistence * @jboss.persistence * datasource = "java:/PostgresDS" * datasource-mapping = "PostgreSQL 7.2" * create-table = "true" * remove-table = "false" * read-only = "false" * list-cache-max = "0" * table-name = "department" * @ejb.util generate="physical" */public abstract class DepartmentBean implements EntityBean { private javax.ejb.EntityContext _entityContext; /** * @ejb.persistent-field * @ejb.persistence * @ejb.interface-method view-type="local" * @ejb.pk-field */ public abstract java.lang.Integer getId(); public abstract void setId(java.lang.Integer id); /** * @ejb.persistent-field * @ejb.persistence * @ejb.interface-method view-type="local" */ public abstract java.lang.String getName(); /** * @ejb.interface-method view-type="local" */ public abstract void setName(java.lang.String name); /** * @ejb.persistent-field * @ejb.persistence * @ejb.interface-method view-type="local" */ public abstract java.lang.String getDetail(); /** * @ejb.interface-method view-type="local" */ public abstract void setDetail(java.lang.String detail); /** * @ejb.persistent-field * @ejb.persistence * @ejb.interface-method view-type="local" * @ejb.relation * name="department_department" * role-name="department-has-department2" * target-multiple = "yes" * target-ejb = "Department" * target-role-name = "department2-belongsto-department" * @jboss.relation * fk-column="parent" * related-pk-field="id" * fk-constraint = "true" */ public abstract java.lang.Integer getParent(); /** * @ejb.interface-method view-type="local" */ public abstract void setParent(java.lang.Integer parent); /** * @ejb.interface-method * @ejb.relation * name = "Department_Employee" * role-name = "Department-has-Employee" * target-multiple = "no" * target-ejb = "Employee" * target-role-name = "Employee-belongsto-Department" * * @jboss.target-relation * fk-column = "departmentID" * related-pk-field = "id" * fk-constraint = "true" */ public abstract Collection getEmployee(); /** * @ejb.interface-method */ public abstract void setEmployee(Collection employee); /** * @ejb.create-method */ public java.lang.Integer ejbCreate(java.lang.Integer id, java.lang.String name, java.lang.String detail) throws javax.ejb.CreateException { setId(id); setName(name); setDetail(detail); return null; } public void ejbPostCreate(java.lang.Integer id, java.lang.String name, java.lang.String detail)throws javax.ejb.CreateException { } /** * @ejb.create-method */ public java.lang.Integer ejbCreate(java.lang.Integer id, java.lang.String name, java.lang.String detail, java.lang.Integer parent)throws javax.ejb.CreateException { setId(id); setName(name); setDetail(detail); setParent(parent); return null; } public void ejbPostCreate(java.lang.Integer id, java.lang.String name,java.lang.String detail, java.lang.Integer parent)throws javax.ejb.CreateException { } public void ejbActivate() throws EJBException, RemoteException { } public void ejbLoad() throws EJBException, RemoteException { } public void ejbPassivate() throws EJBException, RemoteException { } public void ejbRemove() throws RemoveException, EJBException, RemoteException { } public void ejbStore() throws EJBException, RemoteException { } public void setEntityContext(EntityContext entityContext)throws EJBException, RemoteException { this._entityContext = entityContext; } public void unsetEntityContext() throws EJBException, RemoteException { this._entityContext = null; }// * -struts.form// * extends = "org.apache.struts.validator.ValidatorForm"// * include-all = "true"// datasource = "java:/DefaultDS"// datasource-mapping = "Hypersonic SQL"// datasource = "java:/MSSQLDS"// datasource-mapping = "MS SQLSERVER2000"// datasource = "java:/PostgresDS"// datasource-mapping = "PostgreSQL 7.2" } • 源碼分析 其中由該代碼可以自動產生 ibm.cmpr.interfaces.DepartmentLocal.java ibm.cmpr.interfaces.DepartmentLocalHome.java ibm.cmpr.data.DepartmentData.java ibm.cmpr.util.DepartmentUtil.java 四個檔案。 同時,與該 EJB 同時工作的還需要一個 ibm.cmpr.ejb.DepartmentFacadeBean.java 檔案,該檔案與上面的五個檔案形成的 EJB 是一個 fa?ade 的模式,由該檔案可以自動產生 ibm.cmpr.interfaces.DepartmentFacade.java ibm.cmpr.interfaces.DepartmentFacadeHome.java ibm.cmpr.facade.DepartmentFacadeRemote.java 其中最後一個檔案和 Data 包中的檔案構成了用戶端組件 另外的一個 EJB Employee 與此實現相似,共同完成了該項目的工作。 • WEB 實現 系統實現中 WEB 實現是終端使用者看到的介面,要實需求分析中所要求的功能, WEB介面採用了Struts來實現與使用者互動。由於WEB頁頁是UI介面,其編程較為隨意,表現形式豐富,故其代碼量也最大,調試也不容易,該系統中工作量最大的也就是這一塊。項目採用了Resource Properties來實現多語言文字介面,實用性有所加強,也體現了MVC結構模式。 系統還實現了將部門與員工同頁顯示,點擊左邊的部門,右邊的員工列表也只出現指定部門的員工。 • 程式開發 圖 1 Eclipse EJB 開發介面
圖 2 Eclipse EJB 開發介面
圖 3 Eclipse 系統調試介面
圖 4 IE 瀏覽器訪問介面 • 深化 ---- 一個實用的工程 在本文的最後一部份,具體介紹一下實用的項目,這就是 J2ME 手機查詢系統。該系統重點是提供資料查詢,因而應用並不全面,但卻很實用,故在這裡提出。 該項目的客戶是基於 J2ME 的手機使用者。客戶通過 GPRS 或者 CDMA1X 技術與伺服器聯機,執行相關查詢。 情境 1 :當手機使用者得到一個陌生的手機號碼時,他想知道這個號是哪個城市的,該業務名為手機歸屬地查詢; 情境 2 :當手機使用者得到一個互連網 IP 位址時,他想知道這個 IP 位址是哪什麼位置的,該業務取名為 IP 位址查詢; 情境 3 :當手機使用者在使用相關應用程式時,我們可以收集使用者的相關資訊並將其發送至伺服器,以提供更好的支援,本業務取名為資訊採集。 這裡每一個業務都要儲存記錄,所有的查詢和記錄都採用 EJB 實現,與手機互動時採用 http 串連, servlet 響應。 由於時間關係,這裡就不再詳述。 • 與我聯絡 該項目我只用了一周時間就完成了基本架構,在後來的時間裡偶爾加入一些新的功能,隨著對JAVA的不斷理解與學習,我強烈地感覺到JAVA作為一門面象對象的語言,具有無可爭議的優勢。在隨後的時間裡,我感覺到寫一篇這樣的總結性文章非常必要,所以我才用了半天的時間寫下這些文字。 如果這些文字能給您帶來啟發,歡迎與我聯絡: caigao@hotmail.com caigao@vip.sina.com |