簡體   English   中英

如何在 Controller、服務和存儲庫模式中使用 DTO

[英]How to use DTOs in the Controller, Service and Repository pattern

我正在關注 Controller,服務和存儲庫模式,我只是想知道 DTO 是從哪里來的。

controller 是否應該只接收 DTO? 我的理解是你不想讓外界知道底層域model?

從域 model 到 DTO 的轉換應該發生在 controller 還是服務層?

在今天使用 Spring MVC 和交互式 UI 進行編程時,web 應用程序實際上有 4 層:

  • UI 層(Web 瀏覽器、JavaScript)

  • MVC Controller,即用@Controller注解的Spring組件

  • 服務層,即用@Service注解的Spring組件

  • 數據訪問層,即用@Repository注解的@Repository組件

每次這些層與底層交互時,它們都需要發送/接收數據,通常是 POJO,以在層之間傳輸數據。 這些 POJO 是 DTO,也就是數據傳輸對象。

層與層之間只能使用 DTO,它們不一定相同,例如服務層可能會對從數據訪問層接收到的 DTO 應用業務邏輯,因此服務層 API 的 DTO 與數據訪問層 API 不同。 同樣,Controller 可能會重新排列數據以准備呈現(分組、摘要等),因此發送到 web 瀏覽器的數據與從服務層接收的數據不同。

With full abstraction, the Data Access Layer's API should not reflect the technology of the Data Access, ie whether it is using JDBC, JPA, NoSQL, a web service, or some other means of storing/retrieving the data. 這意味着實體類不應出現在數據訪問層之外。

大多數項目不需要這種抽象級別,因此 DTO 通常是一個實體 class,並從數據訪問層一路流向 Controller,在那里它要么被視圖使用,要么被發送到 web 瀏覽器,編碼為 JSON。

這取決於項目的規模和復雜性。 項目越大,使每一層盡可能抽象/獨立變得越重要。

不同的組織遵循不同的模式。 這取決於您遵循哪種模式。 根據我的個人經驗,我遵循以下架構圖。

在此處輸入圖像描述

根據上圖,DTO 到實體對話(反之亦然)將僅在服務層內。

一個簡化的答案可能是:DTO(如果你需要一個,見下文)是一種允許你將特定信息傳輸到其他地方的東西。 這是控制器/適配器/存儲庫/無論你怎么稱呼它的任務。 適配器的任務是從外部世界(系統邊界之外)獲取信息並將這些信息轉換為相應的域 model 以便服務邏輯能夠使用它。

而且,從我的角度來看,這也適用於存儲庫:存儲庫將數據持久化到外部系統(例如數據庫或什至另一個 REST 服務)並在請求時將其帶回。 為此,它可能需要將域 model 轉換為簡化的 DTO 以便能夠持久保存在目標系統中。

適配器的想法是,業務邏輯不需要知道如何轉換 object 以在 REST/SOAP/MySQL/... 協議中表示或傳輸。 這就是適配器的任務。 因此:如果需要,DTO 應該留在適配器中。

你真的需要 DTO 嗎?

DTO 是系統內部數據的另一種抽象。 您還應該考慮是否真的需要它們。 您可能會也可能不會,這取決於您要如何處理這些信息。 如果您使用自己編寫查詢的數據庫來保存數據(這意味着您沒有使用 ORM 映射器),您可能根本不需要 DTO,因為您可以直接從域 model 中提取相關信息。

另一方面,如果您對對象使用反序列化器(例如 Jackson 用於 JSON 或類似的東西),您可能會發現自己需要 DTO,因為這些工具有時需要一些特殊要求才能進行序列化和反序列化您的數據到 object 中。 在這里,您可能需要先使用 DTO,然后才能將其轉換為域 object,反之亦然。


順便說一句:這個問題在 softwareengineering.stackexchange.com 上也得到了很好的回答

正確的方法是 Controller -> 服務 -> 實施 -> 存儲庫

您的存儲庫層可以返回底層 model,當實現層接收到它時,可以將其轉換為您的 DTO。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM