2017-10-10 95 views
0

正如我已經幾次面臨這個問題沒有很好地解決REST API建設者:REST API設計查詢

擁有它似乎很清楚一個實體組織,我們可以休息型號爲/組織,所有的包(GET,POSt,PUT,DELETE,過濾,分頁,...)

請注意,我使用Spring將@RestController類和spring-data PagingAndSortingRepository注入到控制器中。

的問題

/組織/(編號)開始/用戶

這是一個REST API一個完美的URL,但開始引起一些疼痛。

如果我們按照在組織控制器中處理請求的路徑,我們需要將UserDAO添加到控制器,所以我們可以在每個控制器中注入很多DAOS並且每個控制器都負責返回許多不同的對象:組織,用戶,型號等

將問題推到DAO層不是解決方案;試圖使存儲庫返回所有這些不同的對象將不起作用(PagingAndSortingRepository應該抱怨,如果我們試圖與不同的實體一起工作),並且它感覺不到正確的事情,因爲我們強制存儲庫與其領域之外的實體一起工作。

在控制器和DAO之間使用中間層可以工作,一個服務層可以容納這些不同的DAO並提供一個外觀,但又會感覺錯誤:首先,控制器仍在處理許多不屬於它的對象其次,我們有一個沒有真正目的的圖層,可以使用DAO的組合來增長,或者擁有一個可以查詢任何東西的偉大的主DAO對象。

解決這個問題的好方法是什麼?

回答

0

我實際上有幾次類似的問題,並帶有通用的解決方案。讓我們首先重新定義問題:在您的服務或控制器中,您將需要執行可能具有不同類型的操作。 (在你的情況下,你需要訪問一個在不同運行時可能是用戶,組織模型或其他東西的對象。每種訪問類型都是由一個單獨的bean執行的,並且不希望將所有這些bean注入到服務/控制器

解決方案是工廠模式,我做了以下工作:我創建了一個接口和一個抽象類來實現這個接口(在你的情況下它就像GenericDao和GenericDaoImpl)。工廠類(說GeneralDaoFactory)。這個類包含地圖Map<String, GenericDao>在我的泛型類中,我寫了一個構造函數,它將自己添加到Factory中。Factory接收一個名稱(通常是一個類名)和一個GenericDao實例,並將其放入其內部映射然後你只需編寫實現GenericDaoImpl(OrganizationDaoImpl,UserDaoImpl等)和m確信他們被定義爲豆類。在初始化期間,Spring將實例化所有的bean,每個運行其構造函數的bean將自己放入工廠。所以,現在在你的代碼在你的控制器/所有你需要做的服務:

GenericDao userDao = GeneralDaoFactory.getInstance("UserDaoImpl"); 
GenericDao organizationDao = GeneralDaoFactory.getInstance("OrganizationDaoImpl"); 

工廠將被Spring的scienes後面初始化,你不需要任何注入這些DAOS提前。你只需要知道他們的名字,並知道你現在需要哪一個。也曾經,你需要添加一個新道,所有你需要做的是actuially寫入其implementatin,現在可從您的工廠

+0

mmm ...不確定理解,因爲你在最後注入了兩個DAO ......但我想也許你的建議是使用通用DAO的泛型控制器和一個機制來確定具體需要哪些DAO請求,並將在運行時實例化具有特定DAO的特定控制器以提供該特定請求。這是它嗎? – Rafael

+0

@Rafael你錯過了。首先沒有通用控制器 - 只是你的常規控制器。其次,沒有DAO被注入,它們只是在Spring中被創建爲bean,但沒有被注入到任何地方。但是你有一個工廠可以保存對它們的引用 - 每個bean都將自己放入工廠地圖的構造函數中。然後在您的控制器運行時,您可以通過工廠獲得任何DAO –

0

幽州/organization/{id}/users是一個REST API一個完美的URL。

這是一個合理的網址,但我認爲,由於網址跨域,因此只能用於搜索

此外,強制執行單個責任來限制每個控制器的DAO數量。上述URL的支持控制器將類似於OrganizationUsersSearchController。據推測,該方法返回List<User> users爲請求的id。此類與OrganzationsDAO進行交互以獲取某些上下文,並將上下文傳遞給UsersDAO以獲取用戶列表。 DAO可以被服務類包裝,所以控制器只是一個門面。

一旦客戶端擁有users的列表,CRUD操作將由客戶端使用單個域URL(例如/users/{userId})調用。 UserController只與UsersDAO相互作用。再一次,也許將DAO包裝在一個服務類中,這樣控制器就是一個門面。

+0

「只能用於搜索」。 ...我可以同意,仍然看起來像一個非常穩固的其餘網址。 「單一責任被強制限制每個控制器的DAO數量」正是這個問題的出發點。現在我認爲OrganizationUsersSearchController對我來說看起來像是一個糟糕的解決方案,因爲控制器將開始倍增......我們將以可能很多的控制器臨時結束以支持這些操作,同時路由也將是複雜的,因爲起始部分的URl是一樣的。 – Rafael