JDO+JSP2.0開發Web應用嚮導 - 配置篇

JDO+JSP2.0開發Web應用嚮導 – 配置篇

  本文將主要介紹目前流行的JDO規範的應用開發過程。爲簡單起見,將會使用JSP2.0來進行頁面部分的開發,因爲其JSP EL可以大大簡化頁面的開發,節省調試時間,並增加頁面的可讀性。

  以前曾經在CSDN上發表過一篇關於用JDO開發數據庫應用的文章,那只是基於數據庫的簡單的文本模式的程序,僅僅是爲了表達清楚JDO開發的原理和基本過程,現在這篇文章,將更加註重實用性,向各位感興趣的讀者詳細介紹用JDO來開發目前流行的基於Web的三層結構數據庫應用的開發過程。


  在開始開發之前,我們需要先建立開發環境。這裏先說明一下開發用到的第三方產品。

1 系統環境

1.1 MySQL及其JDBC驅動

  我們開發的Web應用是面向數據庫的,當然需要一個底層的數據庫支持。我們這裏使用免費的數據庫產品MySQL作爲底層的關係數據庫。

  先到{www.mysql.com}上,下載目前最新的4.0.16版本,我們下載那個19M大小的不帶安裝程序的ZIP包,我們將這個包解到C:/目錄下,形成一個C:/ mysql-4.0.16目錄(以後就用<mysql>來代表這個目錄),然後運行<mysql>/bin/winMySQLadmin.exe,這樣就將MySQL服務安裝到本機上並啓動就緒了。

  接下來的開發是基於Java的,我們還需要同樣在www.mysql.com上下載最新的JDBC驅動:3.0.9版。我們將下載下來的ZIP包解開,其中的mysql-connector-java-3.0.9-stable/ 目錄中的mysql-connector-java-3.0.9-stable-bin.jar文件就是我們需要的JDBC驅動jar文件了。爲了方便,可以將其改名爲mysql.jar文件,並放到某個目錄中以備使用。

  爲了測試MySQL JDBC的連接,可以去下載一個專門面向JDBC的數據庫操縱工具:SquirrelSQL,它的網址是:{http://squirrel-sql.sourceforge.net}。這是一個免費的軟件。注意連接mysql的時候有兩個問題:

1. 數據庫直接採用MySQL安裝時自帶的“test”庫即可,沒有用戶名和密碼。有些自定義的MySQL安裝會將用戶名設成“root”或“sa”,如果空用戶名連不通,可以試試“root”或“sa”。

2. 爲了能夠使用中文,需要在連接MySQL的JDBC URL中設定使用GBK字符集的參數:
jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=GBK

1.2 JDO與JDOGenie產品

  JDO作爲我們開發Web應用的數據對象包裝層,是本篇文章的核心。爲儘可能簡單和最快地配置起來JDO環境,我們採用目前最簡單易上手的JDOGenie作爲JDO Implementation。除了實現標準的JDO規範之外,這個產品還有以下特點與我們的開發過程有關:

1. 集成的圖形配置界面workbench,基本上可以實現所有配置功能

2. 在集合框架上面,支持java.util.List。這是一個可選的JDO特性。

3. 支持自動維護的雙向關係。這也是JDO2.0將要加入的特性,目前還沒有其他JDO產品能夠做到。

4. 支持Ant集成,可以在其集成配置界面中運行Ant腳本對源代碼進行編譯、類增強等工作

5. 支持查詢結果集的size()方法,返回準確的符合條件的總記錄數。(這個方法在一些JDO產品中將返回0或Integer.MAX_VALUE,這是JDO規範允許的。)

  我們先到JDOGenie的網站{www.jdogenie.com}上下載目前的最新版:2.2.0beta7,是一個ZIP包,解開到一個目錄中就可以使用。我們假定這個解開成了C:/jdogenie-2.2.0beta7/目錄,以後我們用<jdogenie>來代替C:/jdogenie-2.2.0beta7/目錄。

  另外,在下載JDOGenie後還需要申請一個試用的License,根據頁面的提示,我們需要填寫自己的郵箱,和一些其它信息,提交申請後,會一個封帶附件的郵件發過來,這個附件就是試用License,文件名是:jdogenie.license,注意這個附件文件一定要用郵件客戶端程序(如Outlook Express或Foxmail)來保存,很多網友在網易的郵箱mail.163.com網站上通過IE瀏覽器保存這個附件時,這個文件的內容會被改變,不能使用。

  在運行JDOGenie之前,我們需要先在系統中安裝好JDK,推薦最新的JDK1.4.2。安裝好JDK後,要設置一個JDOGenie需要的環境變量:JAVA_HOME,它指向安裝好的JDK的根目錄,比如:C:/JDK1.4.2/。這個變量在下面將要提到的JSP服務器Resin中也需要。

  設置好JDK後,我們直接運行<jdogenie>/workbench.bat,就進入了JDOGenie的集成配置環境,如下圖:
CSDN_Dev_Image_2003-12-62236560.png

  簡單介紹一下這個界面:

1. 頂部是菜單和工具條

2. 左邊是基於JDO開發的幾個工作區(不同職責的人員可能使用不同的工作區),依次是:

a) 樹形圖
  這裏可以看到類及類的內部屬性,方便設置。不過一般不大用

b) UML類圖區
  這裏面可以顯示數據類之間的關係結構圖

c) 類及類屬性列表區,也是最主要的工作區
  這裏列出本項目中用到的數據類及其屬性的各種JDO相關配置,主要的配置工作也在這個區中完成

d) 數據庫創建區
用於將對象模型轉化爲相應的數據庫建表的SQL,並可生成數據庫結構

e) 查詢區,應用投入運行後做維護時很重要的工作區
  可以在這裏進行JDOQL查詢,並可對查詢結果集中的對象進行屬性改動,提交後,數據庫中的數據會更新成改動後的數據。
  也可以在主這裏進行SQL操作,比如某個類加了一個屬性後在這裏執行一個對該表添加字段的SQL操作。

f) 遠程控制檯
  主要是連接遠程的JDOGenie引擎,並觀察服務器運行狀況的工作區,可以查看哪些JDOQL以及生成的SQL運行了多少次,平均佔用時間是多少,以便進行相應的優化(如添加索引、改進查詢代碼等)

3. 底部是狀態條,當某個操作有錯誤時,狀態條上會以紅色顯示最新的錯誤描述,點擊狀態條右邊第一個按鈕可以查看詳細的錯誤信息。狀態條右方顯示當前JDOGenie工作臺佔用了多少內存,如果發現太多內存佔用,估計是垃圾對象太多,可以點擊最右邊的垃圾回收按鈕進行內存釋放。

1.3 Ant:Java批處理工具

  作爲Java開發中的批處理工具(類似C/C++中的Make工具,主要用於編譯、環境設置、文件組織等等),Ant是Apache組織對Java世界最大的貢獻之一,現在已經成爲面向Java開發的批處理方面事實上的標準。關於Ant的介紹文章很多,在{www.CSDN.net}可以找到一大堆,這裏也不多介紹了。我們先去Ant的網站{http://ant.apache.org}下載最新版:1.5.4,下載下來的是一個ZIP包,解開到某個目錄下即可。這裏假定解開到C:/ apache-ant-1.5.4/目錄中,下面採用<ant>來代替C:/apache-ant-1.5.4目錄。

  注意,有些HTTP代理對{http://ant.apache.org/}首頁上的一些腳本有過濾,導致有些用戶可能訪問這個頁面時無法看到內容,這時,可以直接訪問{http://ant.apache.org/bindownload.cgi} 來下載Ant1.5.4。

  爲了以後直接通過DOS命令行處理的方便,我們建議在系統中配置PATH環境變量,將<ant>/bin/目錄加到其中,這樣就可以在命令行狀態直接輸入“ant”來運行“<ant>/lib/ant.bat”命令了。

  Ant是一個Java開發的產品,也是依賴於前面提到的JAVA_HOME環境變量的,Ant通過它找到JDK,從而運行用戶編寫的Ant批處理腳本。

  現在Ant安裝好了,我們再打開JDOGenie,配置一下與Ant的集成:選擇菜單“FileàWorkbench Settings…”,進行JDOGenie的環境配置界面,我們在其中設定Ant的入口程序ant.bat的路徑,如圖:

CSDN_Dev_Image_2003-12-62236562.jpg

  這裏筆者的Ant是安裝在D:/BAK/ant目錄下的,讀者需要根據自己的實際情況設置自己的<ant>/bin/ant.bat路徑。其它設置建議保持不動。

1.4 JSP與Resin服務器

  爲簡單易懂,本文將會以JSP2.0標準來編寫JSP頁面,JSP2.0定義了一個非常有用的數據輸出方式:JSP EL(JSP Expression Language),可以通過標準JavaBean的getXXX()/isXXX()和setXXX()來實現Java對象數據的輸出,並且,JSP2.0還納入了一套標記庫:JSTL,裏面包含很多常用的JSP頁面處理機制,如循環、條件化顯示等等。關於JSP2.0的功能介紹,也可到{www.CSDN.net}上去搜索“JSP 2.0”的相關文章。

  目前JSP2.0規範還未正式出臺,還處於ProposedFinalDraft-3階段,不過很快將會正式發佈。支持JSP2.0的服務器有Tomcat5、Resin3等等,出於方便、易維護的目的,我們選用Resin作JSP服務器。先到Resin網站{www.caucho.com}上下載最新的3.0.4版。下載下來的是一個ZIP包,解開到某個目錄下即可使用。假定我們將包中內容解到C:/下,形成一個C:/ resin-3.0.4/目錄,以後我們使用<resin>來代表“C:/ resin-3.0.4”目錄。

  完成以上工作後,我們進入<resin>/bin目錄,運行其中的httpd.exe程序,就可以看到Resin服務器啓動了。如果希望將Resin安裝成爲系統的一項服務,可以使用httpd.exe –install安裝,並用net start resin來啓動Resin服務。不過爲了方便地查看Resin服務器的輸出日誌,我們不建議安裝Resin爲系統服務,而建議運行httpd.exe來直接啓動Resin。Resin服務器有以下特點:

1. 自動檢測WEB應用的發佈和更新
  通過對<resin>/webapps/下的子目錄進行監測,可以動態地發佈或取消某個web應用,也可以監測某個WEB應用的WEB-INF/web.xml的更新來自動重新發布該應用

2. 自動編譯更新過的java文件,如果Resin檢測到某個應用的WEB-INF/classes/下的java源文件被更新,則會自動編譯該文件

3. 檢測JSP文件的更新,如果某個JSP頁面被更新過,則Resin會重新將它編譯。(這個功能多數JSP服務器都有)

  Resin運行起來後,我們打開Internet Explorer瀏覽器,輸入:{http://localhost:8080/} ,就可以看到Resin的主頁面,表示Resin已經成功運行,如圖:

CSDN_Dev_Image_2003-12-62236564.jpg

2 Web應用:論壇

  在下面這兩章中,我們將會經歷一個論壇項目的開發和維護過程,從最初的非常簡單的需求,到開發、運行,然後再經歷一系列的需求變更和功能改進,來看看使用JDO是如何達到軟件的快速開發與維護和應用的隨需應變的。並且,還會涉及到一些性能優化和傳統JDBC開發很難實現的老問題(如字符串字段長度限制等)。

2.1 準備工作

  在開始開發之前,我們必須先弄清楚一些基本的概念,並按J2EE對Web應用的要求建立相應的運行環境。

2.1.1 認識JDO的開發過程 關於JDO的開發流程,以前的文章和網上一些資料也詳細介紹過,這裏簡單地重複一下:

  先編寫代表數據對象的類,編譯生成.class文件,再編寫描述該類中每個屬性的保存細節的元數據:.jdo文件,然後根據.jdo文件對.class文件進行增強(Enhance),這個數據類就可以在代碼中通過JDO的API進行調用了。圖示如下:

CSDN_Dev_Image_2003-12-62236566.jpg

2.1.2 建立符合J2EE中WebApp規範的應用目錄結構

  爲了減少與Resin的整合配置,我們將論壇應用直接放到<resin>/webapps/下,建立一個名爲bbs的子目錄。這樣,就可以通過在服務器地址後面加入“/bbs/”來訪問這個WEB應用了。

  在bbs目錄中,我們按J2EE規範建立一個“WEB-INF”子目錄,然後在WEB-INF中再建立“classes”和“lib”兩個子目錄,將MySQL的JDBC驅動mysql.jar和JDOGenie的支持包<jdogenie>/lib/目錄下的jdogenie.jar和jta.jar兩個文件複製到這個<resin>/webapps/bbs/WEB-INF/lib目錄中,作爲本應用依賴的第三方組件,並將<jdogenie>/license/jdogenie.license文件複製到<resin>/webapps/bbs/WEB-INF/classes/目錄下。這些配置就是將jdogenie整合到bbs應用中。

  接下來,我們開始確定bbs應用的Java類的包結構。簡單起見,我們將源文件都放到“jdobbs”包中,也就是說,這個應用中涉及的Java源代碼都會以“package jdobbs;”開頭。

  這些目錄都建好以後,我們得到下面的目錄結構:

CSDN_Dev_Image_2003-12-62236568.jpg

  我們先在bbs目錄下放一個index.jsp文件:

<title>JDO BBS on ${pageContext.request.serverName}</title>
您現在的位置:<b>JDO BBS 首頁</b>

<h3>歡迎訪問JDOBBS!</h3>
<p>本系統採用JDO + JSP 2.0 完成<p>

<p>您的瀏覽器類型是:${header['user-agent']}
<p>您的IP地址是:${pageContext.request.remoteAddr}

  然後將Resin啓動,看看效果:

CSDN_Dev_Image_2003-12-622365610.jpg

  好!現在我們的第一個JSP頁面就已經完成了。該頁面代碼中用到的“${pageContext.request.serverName} ”、“${header['user-agent']}”和“${pageContext.request.remoteAddr}”都是JSP2.0中定義的JSP EL表達式。

2.1.3 一個處理JDO資源的工具類:jdobbs.Sys

  我們先來寫一個非常關鍵的工具類:jdobbs.Sys,這個類負責處理一些基本的JDO 存儲管理器獲取、資源釋放、線程同步方面的事務。關於其中的每個細節,都可以用一大篇文章來說明(詳情見{http://www.jdocentral.com/forums/index.php?s=8bf08748ea2b95fe52e0d25c7a489732&act=SF&f=11}中的相關討論),這裏爲了簡單起見,只簡單地描述一下這個工具類的目標: 1. 保證每個JSP頁面請求的服務端線程中所有的業務邏輯方法共享同一個javax.jdo.PersistenceManager,除非在處理過程中間顯式地關閉當前的PersistenceManager。這將採用java.lang.ThreadLocal接口實現

2. 保證每個頁面請求結束後,處理請求過程中涉及的JDO資源全部被釋放(即關閉用到的PersistenceManager)。這將採用javax.servlet.Filter接口實現

  我們來看看下面的Sys.java源碼:

package jdobbs;

import javax.jdo.*;
import javax.servlet.*;
import java.io.*;
import java.util.*;

public class Sys extends ThreadLocal implements Filter {

 /** 獲取PersistenceManagerFactory */
 public static PersistenceManagerFactory pmf() {
 if(pmf == null) {
 Properties p = new Properties();
 InputStream is = Sys.class.getResourceAsStream("/jdobbs.jdogenie");
 try {
 p.load(is);
 } catch(IOException ex) {
 throw new RuntimeException("初始化PersistenceManagerFactory時配置文件讀取失敗!",ex);
 }
 pmf = JDOHelper.getPersistenceManagerFactory(p);
 }

 return pmf;
 }

 /** 獲取PersistenceManager
 * 通過使用ThreadLocal對象,使同一線程中每次調用本方法,都會返回同一PM對象。
 */
 public static PersistenceManager pm() {
 if(threadLocal == null) {
 threadLocal = new Sys();
 }
 return (PersistenceManager)threadLocal.get();
 }

 /** 用於釋放本次線程中使用到的JDO資源
 * @return 是否有未完成的Transaction,便於後臺日誌區別記錄
 */
 public static boolean cleanupResource() {
 return threadLocal != null && threadLocal.cleanup();
 }

 private static PersistenceManagerFactory pmf;

 //============= 以下是ThreadLocal的相關方法==============
 private static Sys threadLocal; //一個用於保證同一線程只訪問同一PM對象的控制器

 /**
 * 獲取一個與當前線程相關的PersistenceManager
 * @return 一個PersistenceManager類型的對象,調用者需要強制轉換一下類型。
 */
 public Object get() {
 PersistenceManager pm = (PersistenceManager)super.get();
 if(pm == null || pm.isClosed()) {
 pm = pmf().getPersistenceManager();
 set(pm);
 }

 return pm;
 }

 /**
 * 釋放所有與本線程相關的JDO資源
 * @return 是否有未完成的Transaction,便於後臺日誌區別記錄
 */
 public boolean cleanup(){
 PersistenceManager pm = (PersistenceManager)super.get();
 if(pm == null) return false;
 if(pm.isClosed()) {
 set(null); return false;
 }

 boolean tsActive = false;
 try {
 Transaction ts = pm.currentTransaction();
 tsActive = ts.isActive();
 if(tsActive) ts.rollback();

 } finally {
 set(null);
 pm.close();
 }

 return tsActive;
 }
 //============= 以上是ThreadLocal的相關方法==============

 //============= 以下是JSP Filter的相關方法==============
 public void init(FilterConfig p0) throws ServletException {}
 public void destroy() {}

 /** JSP頁面(Servlet)處理的過濾器方法,用於JSP執行完畢後檢測並釋放用到的JDO資源 */
 public void doFilter(ServletRequest req, ServletResponse res, FilterChain
  fc) throws ServletException,IOException {
 try {
 fc.doFilter(req,res);
 } finally {
 cleanupResource();
 }
 }
 //============= 以上是JSP Filter的相關方法==============

}

  簡單地說,這個類提供了一個靜態的pm()方法,可以獲取一個JDO的存儲管理器PersistenceManager,這個方法將是以後的代碼中用到最多的方法。

  其中的Sys. pmf()用於獲取PersistenceManagerFactory,這個方法中用到了一個配置文件:jdobbs.jdogenie,這個文件是我們下面將要生成的JDOGenie的配置文件,也就是將在workbench中產生應用配置文件,其中包括數據庫連接地址、用戶、密碼信息,以及一些性能調節的設置。這個配置文件jdobbs.jdogenie將被放置在bbs/WEB-INF/classes/目錄下,以便程序讀取。

  這個Sys類使用了Servlet的過濾接口來保證每個JSP執行完畢後相關的JDO資源得以釋放。因此,編譯這個類時,一定要將Servlet2.4的支持包包含在CLASSPATH中,這個包即是“<resin>/lib/j2sdk-24.jar”文件。爲了以後編譯和進行其它工作的方便,我們編寫一個Ant腳本作爲執行各種批處理(包括編譯)的工具。

2.1.4 配置JSP過濾器

  爲了讓前面的JSP Filter生效,我們需要將其配置到我們的Web應用中去,準確地說,就是創建(或更改)bbs/WEB-INF/web.xml文件,我們更改該文件後,看看它的源代碼:web.xml

<web-app>

<filter>

<filter-name>JDO_Resource_Cleaner</filter-name>

<filter-class>jdobbs.Sys</filter-class>

</filter>

<filter-mapping>

<filter-name>JDO_Resource_Cleaner</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

</web-app>

  這段內容保證了每個JSP頁面請求處理完後,Sys.cleanup()方法將得到執行,以檢測並清除用到的JDO資源。

2.1.5 Ant腳本

  按Ant的標準,我們編寫一個名爲“build.xml”的腳本,並且,爲了配置上的方便,我們將這個文件放到bbs/WEB-INF/目錄下。

  我們看看這個Ant腳本的源代碼:build.xml

<project name="jdobbs" default="enhance">

<property name="resin" location="D:/resin-3.0.4" />

<path id="cp">

<pathelement path="${resin}/lib/jsdk-24.jar" />

<pathelement path="classes" />

<fileset dir="lib" includes="*.jar" />

</path>

<target name="compile">

<javac srcdir="classes" classpathref="cp" debug="true" />

</target>

<target name="enhance" depends="compile" description="Enhance the compiled classes">

<taskdef resource="jdogenie.tasks" classpathref="cp" />

<jdo-enhance project="${ant.project.name}.jdogenie" outputdir="classes" />

</target>

</project>

  將這個文件放到bbs/WEB-INF/目錄下後,我們開啓一個DOS命令行窗口,並進入該目錄,運行一下:“ant compile”,將會看到如下結果:

D:/resin-3.0.4/webapps/bbs/WEB-INF>ant compile

Buildfile: build.xml

compile:

[javac] Compiling 1 source file to D:/resin-3.0.4/webapps/bbs/WEB-INF/classes

BUILD SUCCESSFUL

Total time: 2 seconds

D:/resin-3.0.4/webapps/bbs/WEB-INF>

  這個結果表示我們的Ant腳本已經成功運行了。如果你看到的結果是:

'ant' 不是內部或外部命令,也不是可運行的程序

或批處理文件。

  那就說明你的Ant沒有配置好(比如你開了DOS窗口後纔去更改系統的PATH環境變量),這方面的問題參見前面的Ant安裝與配置進行解決。

  腳本的內容這裏不一一解釋了,請參考Ant的幫助。這裏只說明一下:“enhance”批處理中通過jdogenie.jar中的Ant任務定義,使用了一個“jdo-enhance”任務,這個任務就是用來增強類代碼的。

  好了,進行了以上這些準備工作,爲確信以上的工作都沒有出現錯誤,我們再次從瀏覽器訪問一下首頁,結果與最開始的首頁完全一樣,符合預期。

  接下來,我們就可以開始進行真正的JDO分析和設計了。

2.2 功能需求

  我們最初的需求很簡單,就是讓網友可以在這個系統中交流,以發貼、回覆的形式,簡單地看,可以說這是一個留言本系統。我們要達到以下目標: 1. 網友進入主頁時,系統列出目前所有的主題,按時間順序從近到遠排列。

2. 網友可以在主頁下方的發貼表單中發表新主題,包括標題和內容

3. 其它網友在主頁的貼子列表中點擊某個標題可以閱讀這個主題的詳細內容,包括所有的回貼內容。所有回貼按照時間順序排列在主題主貼後面

4. 可以在主題詳細內容頁面尾部的回貼表單中回覆這個主題

5. 每個網友發表主題或貼子時,系統需要記錄該貼子發表時的客戶端IP地址

6. 系統提供一個高級搜索功能,讓網友可以根據時間、主題標題、內容或回覆內容、IP搜索主題

2.3 分析、數據對象模型與JDO集成

  通過對需求的分析,我們發現,系統中需要存儲的信息就是網友提交的主題或者回復。主題和回覆都需要記錄發貼的網友的IP地址,都有文字內容,但二者又稍有不同,主題可以有一個標題,而回復不需要(目的是爲了方便回貼),另外,一個回覆貼子一定是針對一個主題的。

  從面向對象的角度出發,我們將以上的數據包裝成爲下列的對象模型:

CSDN_Dev_Image_2003-12-622365612.gif

  (後面我們會看到這個圖是如何弄出來的) 

2.3.1 編寫數據類源碼

  我們根據貼子的共性,編寫一個基類:Post(貼子),代表所有的主題和回覆,具有貼子所具備的幾個基本屬性。而主題類我們用Topic來表示,它從Post繼承;回覆類我們用Reply來表示,它有一個屬性:topic,表示所回覆的主題。主題和回覆之間具有一對多關係,體現在Topic.replies和Reply.topic屬性上。爲了JSP2.0中的JSP EL的訪問,我們給每個屬性加上getter/setter(很多IDE工具都提供自動添加getter/setter的功能)。

  下面看看這三個文件的源代碼(注意,都放在WEB-INF/classes/jdobbs/目錄下):

貼子類Post.java:

package jdobbs;

import java.util.*;

/**

* 網友所發表的貼子,包括話題和回覆

*/

public class Post {

/** 貼子內容 */

String content;

/** 貼子內容的長度 */

int length;

/** 發貼時客戶機器的IP地址 */

String ip;

/** 發表本貼的時間 */

Date postTime;

public String getContent() {

return content;

}

public void setContent(String value) {

content = value;

}

public int getLength() {

return length;

}

public void setLength(int value) {

length = value;

}

public String getIp() {

return ip;

}

public void setIp(String value) {

ip = value;

}

public Date getPostTime() {

return postTime;

}

public void setPostTime(Date value) {

postTime = value;

}

}

主題類Topic.java:

package jdobbs;

import java.util.*;

/**

* 話題

*/

public class Topic extends Post {

/** 標題 */

String title;

/** 回覆數 */

int replyCount;

/** 所有回覆 */

List replies;

/** 最後更新,即最後被回覆的時間 */

Date lastUpdate;

public String getTitle() {

return title;

}

public void setTitle(String value) {

title = value;

}

public int getReplyCount() {

return replyCount;

}

public void setReplyCount(int value) {

replyCount = value;

}

public List getReplies() {

return replies;

}

public void setReplies(List value) {

replies = value;

}

public Date getLastUpdate() {

return lastUpdate;

}

public void setLastUpdate(Date value) {

lastUpdate = value;

}

}

回覆類Reply.java:

package jdobbs;

/**

* 回覆

*/

public class Reply extends Post {

/** 所回覆的話題 */

Topic topic;

public Topic getTopic() {

return topic;

}

public void setTopic(Topic value) {

topic = value;

}

}

  爲了在下面使用JDOGenie工具來配置JDO環境,我們先在build.xml所在目錄中運行一下編譯任務:ant compile,編譯這幾個類。

2.3.2 配置JDOGenie,自動創建system.jdo元數據文件、自動建數據庫,等等

  接下來,我們用JDOGenie來實現這個對象模型。注意,接下來這幾步很重要!

  我們進入<jdogenie>/目錄,運行workbench.bat,開始我們的JDO之旅。在主窗口中,我們通過菜單“FileàNew Project…”新建一個JDOGenie項目(這個項目實際上就是JDOGenie的配置文件),在出現的項目文件對話框中,我們選擇<resin>/webapps/bbs/WEB-INF/classes/目錄,並在文件名輸入欄中輸入項目名稱(也就是配置文件的名稱):“jdobbs.jdogenie”,注意,請輸入完整文件名。如圖:

CSDN_Dev_Image_2003-12-622365614.jpg

  點擊確定後,我們將看到一個項目配置設置的對話框。在這個配置對話框的左邊列出配置項,右邊則每項的配置內容。注意,帶目錄圖標的“Project”和“Datastore”也是配置項。我們將在這個對話框中逐項地配置必須的信息:

1. 首先出現的是Project屬性設置,即左邊的Project項,在此項中,我們將“Non-transactional read”檢查框選中,這樣可以不用聲明事務就直接通過存儲管理器(PersistenceManager)訪問數據庫中的對象。如圖:
CSDN_Dev_Image_2003-12-622365616.jpg


2. 接下來是Ant的集成配置,目的是便於直接在工作臺中調用Ant完成數據類的編譯和增強。我們需要輸入ant.bat和build.xml所在的路徑,以便調用。如圖:
CSDN_Dev_Image_2003-12-622365618.jpg

  當然,我們也可以總是手工地在命令行調用Ant,這只需要將上圖中的“Disable Ant”選中即可。

3. CLASSPATH設置。這裏需要加入數據類的根路徑和MySQL的JDBC包,如圖:
CSDN_Dev_Image_2003-12-622365620.jpg


4. 指定Metadata文件。按照JDO規範的要求,必須用.jdo結尾的文件(也稱元數據或描述符)來描述需要存儲的數據類。我們選擇使用CLASSPATH根目錄下的system.jdo文件來描述本系統中所有需要存儲的數據類。先選擇配置對話框左邊的“JDO Meta Data Files”,出現如下對話框:
CSDN_Dev_Image_2003-12-622365622.jpg

  點擊按鈕“New”在WEB-INF/classes/下新建一個system.jdo文件,如圖:
CSDN_Dev_Image_2003-12-622365624.jpg

  點擊“保存”按鈕,回到配置對話框:
CSDN_Dev_Image_2003-12-622365626.jpg


5. 在“Project”部分的剩下幾個配置項主要用於性能優化等方面的調節,我們暫時不考慮。現在直接點擊“Datastore”項,進入數據庫連接信息配置項,如圖:
CSDN_Dev_Image_2003-12-622365628.jpg

  點擊“Choose”按鈕,選擇MySQL類型的數據庫,然後在URL欄中輸入到本機MySQL數據庫的連接:“jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=GBK”,該URL中的GBK設置保證MySQL處理中文時不會亂碼。配置好後,界面如下:
CSDN_Dev_Image_2003-12-622365630.jpg

  現在,我們可以點擊下方的“Test”按鈕來檢測數據庫是否能連通(在此之前,請先檢查一下MySQL是否已經運行)。如果不能連通,請檢查前面的配置是否正確(Classpath配置中是否加入了mysql.jar,URL是否輸入正確)

  到此爲止,“Datastore”部分剩下的幾項配置都可暫不理會,直接點擊最下方的“OK”按鈕關閉配置對話框。這時出現的是一個空的界面,如圖:
CSDN_Dev_Image_2003-12-622365632.jpg

  在這裏,簡單介紹一下JDOGenie的界面,左邊是幾個大按鈕,代表各個方面的功能(前面已經介紹過),從上到下依次是:類樹、類圖、類列表、數據庫結構、JDO查詢、遠程控制檯。後面會介紹這些功能。

  我們現在將前面編寫的數據類添加到項目中,這個步驟將生成JDO規範中要求的.jdo元數據文件。在上面的界面的上半部分的類列表中點擊右鍵,在彈出菜單中選擇“Add Classes…”,這時系統會列出從CLASSPATH中找到的.class類文件,我們選擇其中的三個:Post、Topic、Reply:
CSDN_Dev_Image_2003-12-622365634.jpg

  確定後,系統提示放入哪個元數據文件中,並且列出了前面創建的“system.jdo”文件。直接點擊“OK”即可。我們將看到主窗口變成了下面的樣子:
CSDN_Dev_Image_2003-12-622365636.jpg

  工具條上的第四個按鈕“JDO Metadata Compile”變成了紅色,表示system.jdo中的信息中有歧義,點一下這個按鈕看看詳細原因:
CSDN_Dev_Image_2003-12-622365638.jpg

  原來是系統不知道Topic類中的replies列表(List)的元素類型,在主窗口中選中Topic類,在界面下半部分的類屬性列表中,在replies屬性行上點擊右鍵,選擇“Field Properties…”,進入replies屬性設置的對話框,在對話框中,我們需要設置兩項:第一項,在“Element Type”中選擇jdobbs.Reply類,表示replies列表的元素是Reply對象;第二項,在“Inverse field”中選擇“topic”,表示Topic.replies與Reply.topic是一對雙向關係,任何一邊的改動都會影響到另一邊。如圖:
CSDN_Dev_Image_2003-12-622365640.jpg

  設置好後,點擊這個對話框右上角的“CSDN_Dev_Image_2003-12-622365642.jpg”按鈕關閉它,現在在主窗口中,工具條上的第四個按鈕已經變成綠色(CSDN_Dev_Image_2003-12-622365644.jpg)了,表示元數據已經沒有問題了。我們保存一下項目:“File->Save”,現在就可以增強我們的數據類了。選擇菜單“BuildàCompile & Enhance”或者點擊工具條上的第五個按鈕“CSDN_Dev_Image_2003-12-622365646.jpg”,我們將看到成功編譯和增強的信息:
CSDN_Dev_Image_2003-12-622365648.jpg

  下面我們需要爲我們的數據類建立相應的數據表,我們點擊一下左邊的大按鈕“CSDN_Dev_Image_2003-12-622365650.jpg Database schema operations…”,系統會列出當前的數據類所需要的數據表結構,這裏我們只看到一個表,因爲我們的三個類相互之間是繼承關係,JDOGenie對繼承的類用同一個表來表示。我們選擇菜單“BuildàRecreate Schema”,在數據庫中生成這個表結構(如果是以後改變了類,就不能再重建了,而需要在JDO查詢區“Queries”中用ALTER TABLE的SQL語句來解決,否則會丟失數據):
CSDN_Dev_Image_2003-12-622365652.jpg

  以上的一系列配置過程,就是我們集成JDO的過程,乍一看,好象配置非常複雜,其實前面這一系列過程很快就可以完成,理解了JDO的原理後會覺得很簡單。以後,這個JDOGenie的工作臺workbench.bat就是我們的工作環境了。我們進一步更改類源碼後,只需要在這裏點擊一下編譯按鈕“CSDN_Dev_Image_2003-12-622365646.jpg”,就可以將最新的源文件編譯並增強了。如果增加了更多的數據類,也只需要在這個工作臺中將新的類加入到項目中(即元數據中)即可。

  最後,我們回想一下前面提到的數據類圖,該圖實際上也是在JDOGenie的工作臺中生成的。我們點擊左邊的大按鈕“CSDN_Dev_Image_2003-12-622365656.jpg Class and E/R diagrams”進入類圖區,在窗口中點右鍵,選擇“Choose Classes…”,將所有的數據類都加入到圖中,就會看到包含Post、Topic、Reply三個類的類圖,對位置稍加調整,就可以得到前面的類圖了,如圖:
CSDN_Dev_Image_2003-12-622365658.jpg

  好了,以上所介紹的是JDOGenie的工作臺圖開操作界面的諸多細節,實際上,我們還沒有涉及JDO開發中的核心部分:API的使用。不過相信經過以上的介紹,讀者對作爲一個JDO實現的JDOGenie也有了比較全面的認識了。然而,對於JDO開發來說,不同的產品有不同的配置工具和配置操作,各有特色,比如KodoJDO的數據庫是可以配置爲在運行時動態生成和動態與數據類模型同步的,這一點深受開發人員喜愛。可喜的是,JDOGenie很快也將加進這一非常有利於快速開發和維護的特性。

  在我們開始真正的JDO開發之旅之前,我們先休息一會兒,回顧一下前面提到過的各個層次的服務器,包括數據庫、JSP服務器、JDO產品等等。在本文的《開發篇》中,將給讀者揭開JDO的神祕面紗,讓讀者看清楚開發過程中的每一個細節……

  本文的版權屬於筆者本人,但歡迎轉載,前提是註明出處和原作者。另外,歡迎在我的專欄中查看我的另幾篇文章,並提出寶貴意見!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章