JDK
的新功能
序列化接口(Serializableinterface)
簡化了對象持久化(Persistence)的實現
以下介紹如何通過SMTPE
mail將對象傳送給另一個用戶
摘要
一些應用程序需要以一種非實時的方式(例如旅行指南
錯誤報告(bugreport)
時間表(timesheet)等)和其余用戶共享對象
Java語言開發工具包(JDK)
版提供了一 個重要的功能:java
io
Serializable接口
該技術能讓你知道如何序列化一個對象
然 後用e
mail傳給其它用戶
對象持久化和用戶間對象共享是許多商業解決方案的基礎
例如
一個公司可以用從本公司網址啟動的Applet來完成一個時間表的制作
同樣該公司也可以提供象具有開支報告
旅行指 南
錯誤報告(bugreport)等功能的Applet
在這些情況下
從Applet的使用者獲得的數據需要和負責薪水
付款
旅行房間預訂的人們共享
執行這些職能的人們可能分布在不同的 城市和國家
可能工作在不同的時區
不能希望每個工作人員都能象貓頭鷹一樣在晚上工作以填寫這樣的表格
相同的信息也不應該重新輸入
因此
能夠存儲並且把這些相關對象傳 送到商業應用中是這些applet有別於其它applet的優勢
目前已經有許多方法能實現對象的持久化
例如使用對象數據庫和磁盤文件
同樣的也有許多辦法可以共享對象
例如將數據寫入一個套接字
或者實現一個符合CORBA
SOM的模 型
以上這幾種方案均有自己的優點
當你設計你的商業解決方案時
需要認真地考慮這些方案
但是
還有一種開銷不大但可靠的方法
它使用Internet和Intranet用戶能夠獲取的 技術服務在世界范圍傳送對象的拷貝
它就是簡單郵件傳輸協議
SMTP
用E
mail發送Java對象
存儲和保存對象的一個簡單方法是將對象序列化而後用E
mail將它發送給別的用戶
這種 方法有以下優點:
發送的計算機或NC(網絡計算機)無需硬盤空間
使用現有的系統傳送
排隊
發送對象
允許用戶使用最喜歡的郵件客戶程序來接受郵件
提供簡單的機制將同一對象的拷貝分發給許多人
這種方法也有不足之處:
郵件的傳送可能因為E
mail主機的關機而被較長時間地延遲
所有的主機都可能出現這 種情況
E
mail服務器的錯誤恢復優先級通常比數據庫服務器低
郵件的傳送不能得到保證
在你的E
mail服務器通知你郵件沒有發出時
你不得不重新 發送郵件
E
mail服務器和POP客戶程序的功能不足以處理大量交易信息
這些不足和你使用的應用程序有關
對於很多商業解決方案
這些不足並不重要
作為一個設計人員
你工作的一部分就是在全面考慮價格
性能和需求的情況下確定系統的最佳整體結構
使用Java傳送對象的四個步驟:
Applet必須依次以下面所列出的四個步驟傳送Java對象:
序列化有關對象
發送時選擇Base
編碼方式對序列化對象編碼(RFC
)
與一個SMTP服務器連接
將該對象傳送到這個SMTP服務器
下面將介紹如何用E
mail發送一個假設的
臭蟲
報告到公司的質量保證部門
將對象序列化
JDK
提供的一個奇妙的機制
java
io
Serializable接口
能夠序列化並且重建對象
這個接口能使用存儲對象(writeObject())和恢復對象(readObject())方法函數
在很多 情況下
使用這個接口很方便
只需實現並且調用這兩個方法函數
以下的代碼定義了一個簡單的BugReport對象
它實現了最簡單的序列化接口
import java
Io
*;
public class BugReport implements Serializable {
private Float m_SoftwareVersion; // version number from Help
About
e
g
private String m_ErrorDescription; // Description of error
private int m_Severity; //
=System unusable
=Minor Aesthetic defect
public BugReport (Float SoftwareVersion
String ErrorDescription
int Severity) {
m_SoftwareVersion = SoftwareVersion;
m_ErrorDesctiption = ErrorDescription;
m_Severity = Severity;
}
public BugReport () {} // for reconstituting serialized objects
public void save (OutputStream os)
throws IOException {
try {
ObjectOutputStream o = new ObjectOutputStream(os);
o
writeObject(this);
o
flush();
}
catch (IOException e) {throw e;}
}
public BugReport restore (InputStream is)
throws IOException
ClassNotFoundException {
BugReport RestoredBugReport = null;
try {
ObjectInputStream o = new ObjectInputStream(is);
RestoredBugReport = (BugReport)o
readObject();
}
catch (IOException e) {throw e;}
catch (ClassNotFoundException e) {throw e;}
return RestoredBugReport;
}
}
使用import語句引入I/O包
包括序列化接口
定義類中的成員變量
並指出該類實現了序列化接口
提供一個簡單的構造函數
一個空的構造函數
這個構造函數在重建序列化對象時使用
見以下的例子
定義一個方法函數
它把對象寫入一個已經打開了的ObjectOutputStream
這個方 法函數首先創建一個ObjectOutputStream對象
然後調用writeObject方法函數
最後在 函數返回前顯式清空輸出緩沖區
定義一個方法函數
它從一個打開了的InputStream中讀入一個BugReport對象
注 意
如果輸入流中下一個對象和正在讀入對象的類型不一致時
readObject()將會拋出一 個異常
使用BugReport對象相當簡單
譬如我們想要創建一個新的BugReport對象並且把它存入 一個文件
我們會用到以下代碼:
import java
io
*;
BugReport bug = new BugReport(
Crashes when spell checker invoked
);
FileOUtputStream os = new FileOutputStream(
MyBug
test
);
bug
save(os);
很簡單
對嗎?當然
一旦對象已經被序列化
沒有人能阻止你繼續操縱對象的狀態
上一 個例子中包涵了一個在被寫入磁盤時已經存在對象的拷貝
因此你必須要十分謹慎
以防 在對對象做出所有的修改之後沒有序列化對象
從而丟失了對象的狀態修改信息
以下是怎樣恢復一個對象的拷貝:
import java
io
*
FileInputStream fis = new FileInputStream(
MyBug
test
);
BugReport bug = new BugReport()
restore(fis);
這更簡單!是不是Java的功能越來越強大了?
現在我們修改第二個例子的第
行
使對象被寫入一個字節數組而不是一個文件:
import java
io
*
BugReport bug = new BugReport(
Crashes when spell checker invoked
);
字 節ArrayOutputStream os = new 字 節ArrayOutputStream();
bug
save(os);
好了
我們已經構造了一個對象
並且學會把它序列化後放入一個字節OutputStream
然 後
我們將把這個字節OutputStream轉化為一個Base
編碼的字符串
Base
編碼
目前的Internet E
mail標准
簡單郵件傳遞協議(SMTP)在RFC
中宣布
對於我們來說
RFC
對郵件的內容規定了兩條重要但不難實現的限制
郵件的內容必須全部為
比特的美國ASCII碼
每一行的長度不能超過
的字符
因此為了通過SMTP用E
mail進行傳送
內存的序列化對象必須轉化為和以上相容的格式
RFC
提供了一個可行的方案
它定義了郵件的內容部分
使之能包涵多種形式的數 據
這種標准就是目前眾所周知的MIME
按照RFC
編碼過程為:輸入是
個比特
輸出是
個字節
個比特輸入組從左至右 由
個
比特的輸入組形成
這
個比特被看成
個連續的
比特組
而每個
比特輸入組被翻 譯為Base
碼表中的一個數字
這意味著如果我們有下面的
個字節的輸入
xC
xF
xFF
它將會被轉化為如下 的Base
的編碼:x
xF
xF
x
F
圖Base
編碼實例
Base
編碼似乎有點神秘
但實現它的代碼卻非常簡單
在下面的程序中我們可以看到 這一點
在這個例子中
我們創建了一個新類
Codecs
現在
Codecs有兩個方法函數:一 個用來對字符數組編碼
一個用來對String類編碼
對String類編碼的方法函數簡單地調 用String類的getBytes()函數
然後對返回的結果字符數組進行編碼
我們將增加從Base
解 碼至原先格式的方法函數
public class Codecs {
private Codecs() {} // do not instantiate this class
public final static String base
Encode(String strInput) {
if (strInput == null) return null;
byte byteData[] = new byte[strInput
length()];
strInput
getBytes(
strInput
length()
byteData
);
return new String(base
Encode(byteData)
);
}
public final static byte[] base
Encode(byte[] byteData) {
if (byteData == null) return null;
int iSrcIdx; // index into source (byteData)
int iDestIdx; // index into destination (byteDest)
byte byteDest[] = new byte[((byteData
length+
)/
)*
];
for
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26869.html