軟體項目實訓及課程設計指導——如何在J2EE平臺項目中實現交易日誌、事務控制等功能
1.1 基於面向切面AOP設計思想的系統架構設計實現交易日誌的應用示例
1、面向對象OOP設計中的「開-閉」(OCP,Open-Close Principle)設計原則
隨著軟體應用系統的規模不斷地增大,從而給系統維護人員對軟體應用系統的維護和修改帶來一定的複雜性,這種系統運維工作中的困境促使Bertrand Meyer(貝特朗·梅耶,對象技術大師,發明了Eiffel 語言和按契約設計(Design by Contract)的思想,在1998年提出了面向對象OOP設計中的「開放—封閉」原則。
Bertrand Meyer也是名著《面向對象軟體構造》的作者,法國工程院院士。
該設計原則要求軟體應用系統的開發人員可以在不修改軟體應用系統中現有的功能代碼的前提下(不必改動源程序代碼或者二進位程序代碼、模塊的二進位可執行版本,無論是可連結的庫、DLL或者Java的.jar包文件,都無需要改動),而實現對軟體應用系統的軟體功能進行功能方面的擴展。
2、基於面向切面AOP設計思想的系統架構設計能夠更好地滿足「開-閉」設計原則
面向切面AOP設計思想的本質其實是實現「分散(離)關注」的編程方法——所謂的分離關注就是要求軟體應用系統的設計和開發實現人員要將軟體應用系統中某一通用的需求功能從不相關的各個功能模塊中分離出來,同時也能夠使得其它的功能模塊共享這個通用的功能實現代碼。
由於面向切面AOP也同樣倡導「封裝」和「分離」,因此基於面向切面AOP設計思想的軟體應用系統的系統架構設計實現結果的可擴展性是非常高的。
基於面向切面AOP設計思想的軟體應用系統的系統架構設計實現結果能夠更好地滿足「開-閉」設計原則,因為目前各個應用平臺對面向切面AOP技術的具體實現手段是應用攔截器組件、並且各個攔截器組件可以相互串接組合成為更複雜功能的應用組件。
因此,當軟體應用系統的需求發生變化時,運維人員可以通過替換原有的攔截器組件或者添加新的攔截器組件的方式適應系統需求的變化。
3、在銀行帳戶信息管理系統的示例項目中基於面向切面思想設計和實現交易日誌示例
(1)銀行帳戶信息管理系統需要提供對業務交易日誌記錄的功能
銀行帳戶是開展各項金融業務的基礎,是一切金融交易的門檻,不論什麼樣的金融交易,只要通過銀行,都表現為資金從一個帳戶到另一個帳戶的轉移,都會在帳戶記錄中留下痕跡。讀者對金融行業中的日誌記錄的重要性也應該有所了解,通過採用交易日誌機制等,加強內部制約和監督、審計,提高了銀行業務數據的可靠性和安全性。
為了事後的業務審計和跟蹤,銀行帳戶信息管理系統有必要對每次的帳戶變化的情況進行詳細的記錄,也就是需要對業務交易的過程和結果進行日誌記錄。但對帳戶信息跟蹤的技術實現本質是監控對資料庫系統的訪問,也就是對資料庫表中的記錄的增、刪、改和查等方面的功能操作。
(2)業務交易日誌記錄的數據格式
為了能夠準確地反映每次的帳戶信息的變化狀況,初步規定業務交易日誌記錄的數據格式為下面的各個屬性欄位:交易時間、訪問者的IP位址、操作員的工號ID、操作結果的狀態(成功或者失敗)、操作動作(增加、修改還是刪除)、交易類型(存錢、取錢還是轉帳)、失敗原因說明、具體交易的各種業務數據。
(3)將業務交易日誌記錄的功能單獨設計為一個模塊
為了避免在各個業務功能模塊中直接藕合和重複地編程實現業務交易日誌記錄的功能代碼,在銀行帳戶信息管理系統的架構設計方面應用面向切面的設計思想,業務交易日誌記錄的功能單獨設計為一個模塊——交易日誌記錄攔截器組件。
當某個業務功能類的具體業務方法執行後,通過面向切面AOP所倡導的後置形式的交易日誌記錄攔截器組件實現在交易操作成功或者失敗時都進行記錄。交易日誌的記錄行為主要是依據被攔截的業務對象中的特定的業務處理方法和有關的交易數據。
在執行業務對象中的特定業務處理方法中的程序代碼後,識別業務方法的操作結果的狀態(成功或者失敗)。如果交易成功執行後,則記錄交易成功有關的日誌信息;如果交易執行過程中拋出異常,則記錄交易失敗有關的日誌信息。
1.2 基於面向切面AOP設計思想的系統架構設計實現事務控制的應用示例
1、事務控制技術能夠保證系統數據訪問的一致性
在企業應用系統的設計和開發實現中,單用戶操作的軟體應用系統越來越少了,基本上都是多用戶並發操作和並發訪問軟體應用系統中資料庫表中的數據。在這種應用需求的狀況下,要想保證系統業務的正常進行,保證對系統資料庫訪問中的各種業務數據的一致性是關鍵。
比如在銀行帳戶信息管理系統的轉帳功能實現中,如果技術實現不合理將會造成一個儲戶帳號中的資金減少了,而另一個儲戶帳號中的資金卻沒有增加。保證系統資料庫表中的數據一致性需要對多儲戶並發訪問系統資料庫進行合理的調度和控制,調度和控制的基本單位是應用事務控制技術。下圖所示為保證銀行帳戶信息管理系統中轉帳功能的正確性的事務控制技術的工作原理性圖示。
由於事務是儲戶對帳戶資料庫表中的數據訪問操作的序列集,並且事務具有ACID四個方面的特性(ACID分別代表不可分割性Atomicity、一致性Consistency、隔離性Isolation和穩定性Durability)。因此,軟體應用系統的設計和開發人員合理地應用事務控制技術能夠保證應用系統業務處理過程中的數據一致性和業務邏輯的正確性。
2、在JDBC API系統庫中也提供對事務控制技術的支持
與通過某種特定的資料庫系統中的存儲過程實現事務處理控制相比,JDBC事務處理技術可實現軟體應用系統與物理資料庫系統的分離,不需要系統開發人員考慮不同的物理資料庫系統對事務處理的技術支持的差別,從而增強了軟體應用系統的獨立性。
在基於JDBC的軟體應用系統的開發實現中,事務的啟動是由JDBC驅動程序自動完成的,而事務的終止則可以是自動完成也可以是由軟體應用系統的開發人員在代碼中手動實現。事務到底是自動終止還是手動終止這要取決於在實現的程序代碼中資料庫連接對象中的自動提交狀態的值設置為true還是為false。
JDBC中的事務特點主要體現在:打開一個資料庫連接對象(Connection)時,預設是自動提交(Auto-Commit)模式。也就是說,一條對資料庫的更新SQL語句代表一項事務操作,操作成功後,資料庫系統將自動調用commit()來提交,否則將調用rollback()來回滾。
因此,為了能夠將多個不同的SQL語句組合成一個事務一實現更複雜的數據訪問操作,軟體應用系統的開發人員在編程代碼中需要將自動提交(Auto-Commit)模式屏蔽掉。但JDBC API只支持本地事務((Local transaction))——針對單個資料庫為目標的操作,而不支持分布式事務處理的要求——此時應該要採用Java事務API (JTA,Java Transaction API)。實現對分布式事務處理的技術支持。
3、基於JDBC API事務控制實現的程序代碼示例
在基於JDBC API的事務控制實現的開發中,軟體應用系統的開發人員在編程代碼中可以通過調用Connection 類中的setAutoCommit(false)方法來禁止自動提交;之後就可以把對資料庫操作的多個SQL語句作為一個獨立的事務,在資料庫訪問操作完成後再調用commit()方法來進行整體的提交,倘若其中一個SQL語句所代表的功能操作失敗,都不會執行commit()方法,並且將產生響應的異常;此時就可以在異常捕獲的程序代碼中調用rollback()方法進行回滾恢復修改的相關數據。
下面所示的程序為一個基於JDBC API事務控制實現的代碼示例,請讀者注意其中以黑體標示的語句。
public boolean insertOneUserInfo(UserInfoPO oneRegisterUserInfo) throws WebBBSException{
String insertUserInfoSql="insert into userInfo values(?,?,?,?,?,?,?,?)";
String insertUserContactInfoSql="insert into UserContactInfo values(?,?)";
try{
Connection conn =DriverManager.getConnection("URL","userName","userPassWord");
con.setAutoCommit(false);
PreparedStatement pstmt1 = con.prepareStatement(insertUserInfoSql);
// 參數賦值代碼,在此省略
pstmt1.executeUpdate();
PreparedStatement pstmt2= con.prepareStatement(insertUserContactInfoSql);
// 參數賦值代碼,在此省略
pstmt2.executeUpdate();
con.commit();
}
catch(SQLException e){
try{
con.rollback();
}
catch(SQLException ex){
// 異常處理代碼,在此省略
}
finally{
try{
con.setAutoCommit(true);
}
catch(SQLException e){
// 異常處理代碼,在此省略
}
}
return true;
}
由於基於JDBC API事務控制實現是針對同一個資料庫連接對象完成的,因此該事務控制也就只適用於對單一資料庫系統訪問的軟體應用系統中,而不適用於對多個不同的資料庫系統訪問的軟體應用系統開發中——此時應該要應用分布式事務控制實現技術JTA。
4、在基於JDBC API事務控制技術實現的程序代碼中所反映出的問題
由於需要在多個不同的數據訪問組件提供事務控制,如果採用常規的JDBC事務實現方式將不可避免地會在不同的數據訪問組件中重複地出現上面示例程序中的黑體部分的代碼;而且事務控制的代碼與具體的系統資料庫表數據訪問的DAO組件代碼相互交合在一起,對相關的程序代碼的維護和修改都是比較困難的。
為此,軟體應用系統的設計人員應該要重構軟體應用系統中的事務控制實現,並分離事務控制實現程序代碼與具體的數據訪問的程序代碼之間的耦合關係。
5、在銀行帳戶信息管理系統中基於面向切面思想設計和實現數據訪問中的事務控制
Spring框架中為軟體應用系統提供了聲明形式和編程形式的事務控制技術的支持,軟體應用系統的開發者可以應用Spring框架中對 面向切面AOP技術的支持實現事務控制——它可以在一個應該具有事務控制的方法調用前開始一個事務,在該方法返回時提交或者回滾事務。當然,如果軟體應用系統項目中沒有應用Spring框架,其實也可以採用Java 語言中的動態代理技術實現分離。
所謂的動態代理類是指在程序運行時,運用Java 語言中的反射機制動態創建出。但該動態代理類需要實現InvocationHandler接口,然後借用JDK反射包中的Proxy類為各種接口動態生成相應的代理程序類。
動態代理程序類的字節碼在程序運行時由Java反射機制動態生成,無需程式設計師手工編寫它的原始碼。動態代理類不僅簡化了編程實現工作,而且也提高了軟體應用系統的可擴展性,因為Java 的反射機制可以生成任意類型的動態代理類。
但開發人員的動態代理類必須要實現java.lang.reflect.InvocationHandler接口,並在實現的invoke方法中完成其代理功能的實現。