什麼是DTO

層間數據傳輸的過程就是服務的執行者將數據返回給服務的調用者的過程。在非分佈式系統中由於有類似Open session in view這樣的“怪胎解決方案”的存在,所以層間數據傳輸的問題並沒有充分暴露出來,但是在分佈式系統中我們就能清楚地意識到層間數據傳輸的問題,從而能夠更合理的進行設計。爲了暴露更多問題,本章討論的層間數據傳輸假定的場景是“服務器將執行的數據結果如何傳遞給遠程客戶端”,儘管在實際場景中服務的提供者和服務的調用者有可能處於同一虛擬機中(比如Web端與應用服務部署在同一服務器中)。

10.1  什麼是DTO

在分佈式系統中,客戶端和服務器端交互有兩種情形:第一個是客戶端從服務器端讀取數據;第二個是客戶端將本身的數據傳遞給服務器端。

當有客戶端要向服務器端傳輸大量數據的時候,可以通過一個包含要傳輸的所有數據的方法調用來完成。這在小數據量的時候缺點並不明顯,但是如果要傳遞包含有大量信息的數據的時候,這將變得難以忍受。下面的方法是任何人看了都會害怕的:

public void save(String id,String number,String name,int type,int height,

int width,BigDecimal weight,BigDecimal price,String description)

這種接口也是非常的脆弱,一旦需要添加或者刪除某個屬性,方法的簽名就要改變。

當客戶端要從服務器端取得大量數據的時候,可以使用多個細粒度的對服務器端的調用來獲取數據。比如:

ISomeInterface intf = RemoteService.getSomeInterface();

System.out.println("您要查詢的商品的資料爲:");

System.out.println("編號:"+intf.getNumber(id));

System.out.println("姓名:"+intf.getName(id));

System.out.println("類型:"+intf.getType(id));

System.out.println("高度:"+intf.getHeight(id));

System.out.println("寬度:"+intf.getWidth(id));

System.out.println("價格:"+intf.getPrice(id));

System.out.println("描述信息:"+intf.getDescription(id));

這種方式中每一個get***方法都是一個對服務器的遠程調用,都需要對參數和返回值進行序列化和反序列化,而且服務器進行這些調用的時候還需要進行事務、權限、日誌的處理,這會造成性能的大幅下降。如果沒有使用客戶端事務的話還會導致這些調用不在一個事務中從而導致數據錯誤。

系統需要一種在客戶端和服務器端之間高效、安全地進行數據傳輸的技術。DTO(Data Transfer Object,數據傳送對象)是解決這個問題的比較好的方式。DTO是一個普通的Java類,它封裝了要傳送的批量的數據。當客戶端需要讀取服務器端的數據的時候,服務器端將數據封裝在DTO中,這樣客戶端就可以在一個網絡調用中獲得它需要的所有數據。

還是上面的例子,服務器端的服務將創建一個DTO並封裝客戶端所需要的屬性,然後返回給客戶端:

ISomeInterface intf = RemoteService.getSomeInterface();

SomeDTOInfo info = intf.getSomeData(id);

System.out.println("您要查詢的商品的資料爲:");

System.out.println("編號:"+info.getNumber());

System.out.println("姓名:"+info.getName());

System.out.println("類型:"+info.getType());

System.out.println("高度:"+info.getHeight());

System.out.println("寬度:"+info.getWidth());

System.out.println("價格:"+info.getPrice());

System.out.println("描述信息:"+info.getDescription());

使用DTO的時候,一個主要問題是選擇什麼樣的DTO:這個DTO能夠容納哪些數據,DTO的結構是什麼,這個DTO是如何產生的。DTO是服務器端和客戶端進行通信的一個協議格式,合理的DTO設計將會使得服務器和客戶端的通信更加順暢。在水平開發模式(即每個開發人員負責系統的不同層,A專門負責Web表現層的開發,B專門負責服務層的開發)中,在項目初期合理的DTO設計會減少各層開發人員之間的糾紛;在垂直開發模式(即每個開發人員負責不同模塊的所有層,A專門負責庫存管理模塊的開發,B專門負責固定資產模塊的開發)中,雖然開發人員可以自由地調整DTO的結構,但是合理的DTO設計仍然會減少返工的可能性。

實現DTO最簡單的方法是將服務端的域對象(比如Hibernate中的PO、EJB中的實體Bean)進行拷貝然後作爲DTO傳遞。採用域對象做DTO比較簡單和清晰,因爲DTO與域模型一致,所以瞭解一個結構就夠了。這樣做也免去了DTO的設計,使得開發工作變得更快。這種做法的缺點是域DTO的粒度太大以至於難以滿足客戶端的細粒度的要求,客戶端可能不需要訪問那些域中的所有屬性,也可能需要不是簡單地被封裝在域中的數據,當域DTO不能滿足要求的時候就需要更加細粒度的DTO方案。目前主流的DTO解決方案有定製DTO、數據傳送哈希表、數據傳送行集。

發佈了2 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章