試圖重構一些代碼。我看到有些類正在創建DTO對象,這些對象正在服務層中傳遞,並由@RestController稍後返回。據我所知,最好只在控制器中構建數據傳輸對象,並將它們傳遞給視圖,特別是當我們使用類似WrapperDTO<T>
的get和set值時。當我們用複雜的對象或簡單的數據類型構建WrapperDTO時,可能會有差異。所有oppinions將不勝感激。數據傳輸對象DTO要在哪裏構建
回答
DTO可用於在應用程序的不同層之間傳輸數據:DAO,Service,Facade,Controller。根據我的經驗,DTO是一個有見地的話題。
在我看來,轉換越晚越好,如果不需要轉換就更好。通常,後者處於應用程序邊界。 DTO不是免費的,它涉及到繪圖和支持。因此,當存在領域模型不匹配或模型技術不匹配時,DTO將是有意義的。欲瞭解更多信息,你可以看看LocalDTO article and the associated link。
如果我專注於服務 - >門面 - >控制器層:
服務:他們在做服務的東西,他們可能會叫對方做自己的處理。如果您的域模型在整個服務範圍
service => facade
中保持一致,則將結果轉換爲DTO爲時尚早。外牆:他們可以編排服務和轉換輸入/輸出。以我的觀點來看,它將成爲轉換或轉換DTO的合適地點。但只有當它需要時,即。因爲您的域模型必須跨越此邊界進行轉換(過濾字段,聚合...)
網關/控制器:它們位於應用程序邊界。它們的邏輯很簡單,簡化爲邊界邏輯。門面和控制器之間的關係通常是
one <-> one
。 ***合併外牆及控制器通常意義
因此,在我的觀點,你的第一個建議是更適應如。 UserController....
。最重要的是要保持務實。
一個很好的,平衡的答案。我在DTO和域對象上寫了幾個帖子,大體上也得出了相同的結論。 https://notesofapragmaticprogrammer.wordpress.com –
我會說最好在服務層上創建DTO。
控制器不能知道業務邏輯細節。例如。我們需要返回用戶信息,但一些字段(密碼等)必須排除在外。這些字段存在於用戶實體中,但必須從DTO中刪除。
另一種情況我們在Controller上得到了SomePaginationDTO
,我們仍然需要通過DTO來服務解析過濾器,應用排序,限制結果等。所有的邏輯都是服務責任的一部分。所以我會通過SomePaginationDTO
來服務。
我有不同的想法。我完全同意SomePaginationDTO,我使用動態DTO(地圖),甚至可以請求「僅某些字段」服務(以類似的方式進行排序,過濾和分頁)。如果我想'用戶無密碼',我使用這種機制。或者,我從控制器的服務中獲得一個實體(或完整的DTO),並在控制器中創建「(動態)dto無密碼」。如果我沒有字段選擇機制,我不會在服務上創建一個getUserNoPassword()方法,我會在控制器中對DTO進行轉換。我不確定這是商業邏輯,對我來說似乎更多的控制器視圖邏輯。我錯了嗎 ? –
對於我來說,控制器不應該知道如何限制數據或者應該如何返回數據。這是IMHO服務的一部分。控制者的職責是數據傳輸(marshall unmarshall),安全檢查,過濾,錯誤處理。 – StanislavL
謝謝。但是如果服務沒有實現選擇列?或者,也許更常見:如果該服務沒有實現排序或分頁,那麼您在哪裏執行內存中的排序或分頁?我在控制器中執行此操作,並以相同的方式在不支持服務時執行屬性/列選擇。它也可能只是一個UI功能,可能是每個用戶的偏好。我真的很想聽聽這個意見。 –
我會說沒有正確的方法來執行此操作。這取決於DTO的用途。
我發現了一個簡單的規則,我可以在哪裏使用DTO服務級別和不在哪裏:如果服務級別只有一個客戶端,我在服務級別使用DTO。如果有兩個或更多的客戶端,最好不要在服務級別使用DTO。
讓我更詳細地解釋了這一點:
基本上很顯然,這還不包括DTO到服務級別需要更多的努力。因此,如果只有一個客戶端,我會保持簡單,並使用DTO作爲服務方法的返回類型。
如果有多於一個客戶端的服務,最有可能的客戶端將需要不同的DTO(例如我想有一個對象的json
和csv
表示)。在這種情況下,我不會從服務中返回DTO。否則,我就需要爲每個DTO,或不同的服務方法等有不同的服務
注:我不是說,如果你沒有在服務級別使用DTO必須移動轉換邏輯進入控制器級別。我仍然認爲控制器級別必須儘可能簡單。您可能在控制器和服務之間存在一些中間轉換級別 - 不舒服,但是它有好幾種服務。
作爲其他問題的一部分,我發現了一個很好的答案。當然這/我的答案不參與賞金。這只是一個人的靈感來解釋如何實施現在的事情。所以看看:
- 模型類。他們沒有得到任何東西的獲取者/定位者。它 取決於模型邏輯。否則,你會得到模型,你可以很容易地打破一致性 。或者哪裏有許多不明顯的事情。假設你有 有User.registrationDate字段。當你構建一個新的用戶對象時,你不應該忘記通過 指定的字段註冊日期字段。所以,只需在您的 構造函數中添加registrationDate初始化並刪除setter!
- 存儲庫接口就在您的模型中。假設你有一些 業務邏輯取決於現有的存儲對象。您不能將 明確地從您的域邏輯引用到基礎結構 依賴關係(如JPA,Hibernate,JDBC等)。因此,您從接口查詢此存儲的 對象。
- 商業服務(可選)。他們執行一些複雜的邏輯,涉及許多不同的實體,不包括安全性和事務管理。你的問題是關於它的。是的,如果您需要在您的域邏輯中查詢實體的 ,請將查詢放入存儲庫 並從您的業務服務中調用它。
- 基礎架構包內的存儲庫實現。使用JPA或mockito或其他方法實現 存儲庫接口。他們 也不包括安全性和交易。
- 應用程序服務(可選)。如果有一些複雜的與基礎設施或安全檢查的交互 。
- 遠程外觀界面。客戶端和服務器僅通過 遠程門面接口進行通信。
- 遠程外觀實現(控制器)。將厚實體 對象轉換爲細DTO(數據傳輸對象)。所有交易 分界和安全在這裏(通常使用註釋)。
您對這種設計有什麼看法?它適用於衆所周知的彈簧mvc嗎?
- 1. JAX-RS是否需要數據傳輸對象(DTO)?
- 2. 數據傳輸對象(DTO)的要點是什麼?
- 3. 如何有效地使用DTO對象(數據傳輸對象)?
- 4. 使用DTO傳輸數據
- 5. 在Java中的DTO(數據傳輸對象)和類對象之間的區別?
- 6. Java EE DAO/DTO(數據傳輸對象)設計模式
- 7. 依賴注入 - 與數據傳輸對象(DTO)一起使用?
- 8. 如何從ContainerRequestContext獲取數據以構建DTO對象
- 9. 從域對象構建DTO的設計
- 10. 數據傳輸對象(DTO)與愚蠢的業務對象之間的區別?
- 11. C#中的DTO(數據傳輸對象)和代理對象之間的差異
- 12. 如何告訴cmake在哪裏輸出其構建數據?
- 13. 我應該在哪裏進行轉換:域對象<-> DTO?
- 14. JPA模式:從實體生成數據傳輸對象DTO並將DTO合併到數據庫
- 15. 何時在MVC4應用程序中使用DTO(數據傳輸對象)?
- 16. 傳輸LINQ數據對象
- 17. Stringbuilder對象在哪裏創建?
- 18. Rails在哪裏創建:通過對象
- 19. DDD:在哪裏創建實體對象?
- 20. 逐步構建複雜的對象。在哪裏保存?
- 21. 對於etl,我可以在哪裏下載數據以構建數據倉庫
- 22. 從哪裏對象計數對象
- 23. 數據傳輸對象 - 在DTO中執行映射還是在業務對象中執行映射?
- 24. 建造輸出在哪裏?
- 25. 當我從DTO構建EF對象時,如何將EF對象層次結構保存到數據庫?
- 26. 如何使用EF連接兩個數據傳輸對象(DTO)? [編輯]
- 27. 如何將http狀態添加到所有響應dto(數據傳輸對象)?
- 28. 在類中創建對象 - 該對象在哪裏?
- 29. 要傳輸文件的對象數組
- 30. 舊對象在哪裏?
我想你應該看看[這裏](https://softwareengineering.stackexchange.com/questions/277817/what-is-the-best-way-to-create-dtos-from-entities-and-更新實體從dtos) –