以前我剛開始接觸Flex1.5的時候怎么都不明白Flex是如何連接數(shù)據(jù)庫的,雖然知道有三種方式,但還是不懂,這個問題讓我頭痛了好長時間,后來終于恍然大悟。今天寫一篇如何在Flex中使用RemoteObject利用JAVA對象連接數(shù)據(jù)庫的教程,給初學(xué)者做參考,高手就不需要看了。
首先,做一點說明。Flex是不能直接連接數(shù)據(jù)庫的,這一點大家需要知道,它只能間接地連接數(shù)據(jù)庫。Flex中提供了三種方式:HttpService,WebService 和 RemoteObject。其中HttpService可以直接獲取XML中的數(shù)據(jù),還可以通過JSP,ASP以及PHP讀取數(shù)據(jù)庫中的數(shù)據(jù),這個比較簡單,而且網(wǎng)上也有很多例子,我就不多說了。WebService我不懂,請自己查資料。我一直用的是JAVA對象連接數(shù)據(jù)庫,感覺這個挺方便,而且J2EE的技術(shù)已經(jīng)很成熟。今天的教程就是以 Flex + JAVA + SQLServer 獲取數(shù)據(jù)庫公告信息為例簡單說一下RemoteObject的用法。 前提 1.確保你安裝了Flex Data Service。這個對于單個CUP無限APP是免費的,可以去Adobe下載。如果只是讀取XML文件是不需要這個的,連接數(shù)據(jù)庫就需要它了。 2.安裝了Flex Builder或者有Flex SDK。我這里使用的是Flex Builder(IDE就是方便啊 ^_^)。 3.安裝了SQLServer數(shù)據(jù)庫。 4.安裝了JRUN或者tomcat或其它的J2EE容器,因為發(fā)布的時候我們的程序要運行在J2EE平臺上。 5.安裝了JDK。 JDK版本問題:由于我用的是Flex Data Service自帶的JRUN,它不支持JDK5.0,所以我用的是JDK1.4.2,版本問題大家看具體情況來。 第一步:創(chuàng)建數(shù)據(jù)庫 這里我們有一個公告表,表名為Bulletin。結(jié)構(gòu)如下: ![]() 字段名稱 字段類型 說明 ID 自動編號 自動編號 title Nvarchar(100) 題目 date datatime 日期 author Nvarchar(20) 作者 contents ntext 內(nèi)容 在數(shù)據(jù)庫中創(chuàng)建這個表。保存之后進入下一步。 第二步:在JAVA中編寫獲取公告的代碼 首先,我們要創(chuàng)建一個公告類來專門保存獲取的公告信息,代碼如下。 NoticeInfo.java ![]() package net.zhuoqun.connectDB;
import java.util.Date; public class NoticeInfo { private String title; // 標(biāo)題 private String author; // 作者 private String content;// 內(nèi)容 private Date dates; // 時間 public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } ……………… // 其它get 和 set 方法。 } 創(chuàng)建好這個之后我們要創(chuàng)建一個數(shù)據(jù)查詢類:DataServiceImpl.java 來查詢數(shù)據(jù)庫,并將查詢結(jié)果傳給將要創(chuàng)建的Flex程序。由于我們不清楚有多少條記錄,所以就借助一下JAVA中的ArrayList這個類,它位于java.util 包中。先創(chuàng)建一個ArrayList: ![]() ArrayList noticeList = new ArrayList(); // 這里我沒有用泛型,因為我用的JDK1.4.2.
查詢數(shù)據(jù)庫之后,每讀取一條記錄就添加到 noticeList。 ![]() while(rs.next()){
NoticeInfo temp = new NoticeInfo(); temp.setAuthor(rs.getString("author")); temp.setContent(rs.getString("content")); temp.setDates(rs.getDate("date")); temp.setTitle(rs.getString("title")); noticeList.add(temp); } 查詢完畢之后你就可以把這個noticeList傳回去,你也可以傳回去一個 NoticeInfo 數(shù)組: ![]() NoticeInfo[] notices = new NoticeInfo[noticeList.size()];
for(int i=0;i<noticeList.size();i++){ notices[i] = (NoticeInfo)noticeList.get(i); } return notices; 我這里用的是后一種方法。如果你直接把noticeList傳回去的話,記住一點,JAVA的ArrayList類型的對象到了Flex中會變成ArrayCollection類型的。 現(xiàn)在JAVA部分的代碼就寫好了。 DataServiceImpl.java 的全部代碼如下: ![]() package net.zhuoqun.connectDB;
import java.sql.*; import java.util.ArrayList; import java.util.Date; public class DataServiceImpl { private Connection conn = null; private Statement stmt = null; // 以下是數(shù)據(jù)庫以及驅(qū)動信息 public final static String DRIVER = "com.microsoft.jdbc.sqlserver.SQLServerDriver"; public final static String CONN_STR_PRE = "jdbc:microsoft:sqlserver://"; public final static String HOST_NAME = "localhost:1433;"; public final static String DATABASE_NAME = "DatabaseName=mydata"; public final static String USERNAME = "aaa"; public final static String PASSWORD = "aaa"; public DataServiceImpl(){ } // 查詢數(shù)據(jù)庫 private ResultSet executeQuery(String sqlText){ try{ Class.forName(DRIVER); }catch(ClassNotFoundException e){ e.printStackTrace(); } try{ conn = DriverManager.getConnection(CONN_STR_PRE + HOST_NAME + DATABASE_NAME, USERNAME, PASSWORD); stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sqlText); return rs; }catch(SQLException e){ e.printStackTrace(); } return null; } // 查詢公告. 這個是本程序的關(guān)鍵代碼 public NoticeInfo[] getNotices(){ ArrayList noticeList = new ArrayList(); String sqlText = "select author,content,date,title from Bulletin"; ResultSet rs = executeQuery(sqlText); try{ while(rs.next()){ NoticeInfo temp = new NoticeInfo(); temp.setAuthor(rs.getString("author")); temp.setContent(rs.getString("content")); temp.setDates(rs.getDate("date")); temp.setTitle(rs.getString("title")); noticeList.add(temp); } NoticeInfo[] notices = new NoticeInfo[noticeList.size()]; for(int i=0;i<noticeList.size();i++){ notices[i] = (NoticeInfo)noticeList.get(i); } return notices; }catch(SQLException e){ e.printStackTrace(); return null; } } } 第三步: 配置Flex Data Service 1,把剛才寫的JAVA文件編譯。打開FDS的安裝文件夾,將編譯的文件拷貝到\jrun4\servers\default\flex\WEB-INF\classes 文件夾中,進行下面的配置。 2.打開FDS的安裝文件夾。進入 jrun4\servers\default\flex\WEB-INF\flex 目錄。里面是關(guān)于Flex Data Service 的配置文件,我們這里只看RemoteObject如何配置,其它配置信息請自己看幫助?,F(xiàn)在我們打開里面的 remoting-config.xml 文件。向里面添加如下信息,作為<service>的子標(biāo)簽: ![]() <destination id="dataService">
<properties> <source>net.zhuoqun.connectDB.DataServiceImpl</source> </properties> </destination> 當(dāng)你設(shè)定了 destination 的時候,你就引用了了可以用來連接相應(yīng)類的信息通道(messaging channel)。它的 id 必須在文件中是獨一無二的。 source屬性是指你編譯的JAVA類在classes文件夾中的路徑。由于我的DataServiceImpl類在classes\net\zhuoqun\connectDB中,所以source的值為net.zhuoqun.connectDB.DataServiceImpl。記住,不要寫.class后綴。<properties> 標(biāo)簽還可以有一個<scope>子標(biāo)簽,其作用我在這里就不說了,大家自己看相關(guān)文檔(關(guān)于FDS的配置其實有很多東西,這些在幫助文檔里都有,我這里不多說了,也說不過來,自己看吧)。 現(xiàn)在我們已經(jīng)配置好了后臺的 FDS,做完了整個程序的大部分工作,接下來就是前臺Flex程序調(diào)用的事情了。 第四步:創(chuàng)建Flex程序 打開Flex Builder,新建一個工程 ConnectDB。菜單欄中 File -> New -> Flex Project,這時會彈出一個對話框,選擇 Flex Data Service最下面的,如圖: 其中還有兩個編譯選項,分別是“在Flex Builder中本地編譯”(編譯成SWF和HTML頁放到服務(wù)器)和“當(dāng)用戶瀏覽頁面時再編譯”,你可以根據(jù)需要選擇,這里我們選擇第一個。 接下來設(shè)置FDS服務(wù)器的根目錄和路徑: 輸入工程的名稱和目錄: 然后點擊下一步設(shè)定類路徑以及輸出文件夾等等: ![]() 這些都設(shè)定好之后點擊 完成 就創(chuàng)建了一個Flex工程。 第五步:通過 RemoteObject 訪問數(shù)據(jù)庫 打開工程中生成的主文件 ConnectDB.mxml,聲明一個 RemoteObject : ![]() <mx:RemoteObject id="getData" destination="dataService" result="proccessResult(event.result)" fault="Alert.show(event.fault.faultString,‘Error‘)"/>
其中 destination 的值是剛才我們在配置 FDS 的時候設(shè)定的 destination。 result 表示在這個RemoteObject 成功返回之后所要做的動作,這里我們調(diào)用一個方法 proccessResult()來處理返回的數(shù)據(jù),它的參數(shù) event.result 就是從服務(wù)器段獲得的數(shù)據(jù),數(shù)據(jù)是作為一個對象傳過來的。 fault 表示在這個RemoteObject請求失敗時要做的處理,這里我們會彈出一個顯示錯誤信息的對話框。接下來我們要聲明一個DataGrid控件來顯示公告的標(biāo)題和發(fā)布日期: ![]() <mx:DataGrid id="myDG">
<mx:columns> <mx:DataGridColumn headerText="標(biāo)題" dataField="title"/> <mx:DataGridColumn headerText="發(fā)布日期" dataField="dates" labelFunction="formatDate"/> </mx:columns> </mx:DataGrid> 其中headerText是顯示在上方的表頭,dataField表示要顯示的數(shù)據(jù)域,為什么數(shù)據(jù)域是title和dates呢?因為我們傳回的是一個 NoticeInfo 對象數(shù)組,雖然它是作為一個對象傳回來的,但是其中的數(shù)據(jù)結(jié)構(gòu)并沒有變,那些數(shù)據(jù)域的名字也沒有變,所以我們可以根據(jù) NoticeInfo 中的變量設(shè)定dataField。labelFunction 屬性是用來格式化顯示的,因為傳回來的是格林威治時間,所以我們需要將其格式化然后顯示出來。注意,這里只是顯示兩個數(shù)據(jù)域,并不代表其它的數(shù)據(jù)都沒有了,它們?nèi)匀淮嬖冢皇菦]有顯示出來。 接下來,在 <mx:Script> 標(biāo)簽中編寫proccessResult()方法和格式化日期的 formatDate方法: ![]() private function proccessResult(result:Object):void
{ myDG.dataProvider = ArrayUtil.toArray(result); } private function formatDate(item:Object,column:DataGridColumn):String { return df.format(item.dates); } // df 是一個 DateFormatter,在下面會給出。關(guān)于如何格式化DataGrid的顯示 // 以及DateFormatter這里就不討論了,幫助里寫得很清楚 這個函數(shù)只是簡單地將獲得的數(shù)據(jù)傳給 myDG 的 dataProvider。result 的類型是Object,因為數(shù)據(jù)是作為一個對象傳過來的。之所以調(diào)用 ArrayUtil.toArray() 這個方法,是因為返回的記錄可能只有一條,而myDG 的 dataProvider顯示單個對象的時候可能會出錯,所以安全起見先將其轉(zhuǎn)換成數(shù)組。 最后,我們編寫調(diào)用 RemoteObject 的方法,使其在程序啟動時就調(diào)用。 ![]() private function initApp():void
{ getData.getNotices(); } 其中 getData 是RemoteObject的 id,getNotices()是DataServiceImpl.java中的方法。在這里可以直接調(diào)用它。當(dāng)然,如果DataServiceImpl.java有其它方法,也可以通過這種方式直接調(diào)用。接下來設(shè)定組件創(chuàng)建完畢時調(diào)用 initApp()方法,在 <mx:Application>中添加一個creationComplete屬性: ![]() <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" fontSize="12"
creationComplete="initApp()"> …………………… ConnectDB.mxml的全部代碼: ![]() <?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" fontSize="12" creationComplete="initApp()"> <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.utils.ArrayUtil; private function initApp():void { getData.getNotices(); } private function proccessResult(result:Object):void { myDG.dataProvider = ArrayUtil.toArray(result); } private function formatDate(item:Object,column:DataGridColumn):String { return df.format(item.dates); }// df 是一個 DateFormatter,在下面會給出。關(guān)于如何格式化DataGrid的顯示 // 以及DateFormatter這里就不討論了,幫助里寫得很清楚 ]]> </mx:Script> <mx:DateFormatter id="df" formatString="YYYY-MM-DD"/> <mx:RemoteObject id="getData" destination="dataService" result="proccessResult(event.result)" fault="Alert.show(event.fault.faultString,‘Error‘)"/> <mx:DataGrid id="myDG"> <mx:columns> <mx:DataGridColumn headerText="標(biāo)題" dataField="title"/> <mx:DataGridColumn headerText="發(fā)布日期" dataField="dates" labelFunction="formatDate"/> </mx:columns> </mx:DataGrid> </mx:Application> 整個工程終于完成,啟動JRUN,然后運行。結(jié)果如圖所示: ![]() 需要注意的地方: 1.注意你的 JRUN 或者其它容器對JDK版本的支持,不小心就會出錯。 2.在運行時如果控制臺出現(xiàn)了 找不到/messagebroker/amf文件 的錯誤,請看我以前找到的解決辦法:http://www./article.asp?id=180 3.運行的時候如果是獲取數(shù)據(jù)出錯的,控制臺一般都會有提示信息,可以給你很多提示。 總結(jié) 這篇簡單的教程算是給一些 Flex 的初學(xué)者一個入門,我技術(shù)也有限得很,寫得不好,勿怪。另外限于篇幅,很多細(xì)節(jié)方面我都沒有寫出來,如果有什么看不明白的就去看幫助文檔,那是最好的教科書。 |
|