2013-05-22 134 views
6

編寫RESTFul api應用程序的最佳實踐之一是添加版本控制。例如:使用Spring實現REST Api

http://my-server/api/v1/getData 
http://my-server/api/v2/getData 

我們的應用程序公開了使用Spring框架的REST API。我們將一個類標記爲Controller,使用RequestMapping註釋將URL映射到一個函數,並添加一些被翻譯成json對象的對象。

例如:

@RequestMapping(method = RequestMethod.POST, value = "/api/v1/getData") 
public @ResponseBody ResponseDataDTO getData(@RequestBody OperationsDetailsTDO details) {...} 

現在,我們希望提供API的第二個版本。大約2/3的功能保持不變,1/3正在改變。這些更改都是在邏輯和JSON對象中進行的。

我想知道如何設計代碼。我認爲,這種代碼是難以管理:

@RequestMapping(method = RequestMethod.POST, value = "/api/{version-var}/getData") 
public @ResponseBody ResponseDataDTO createReleaseFromTemplate(@PathVariable("version-var") Integer version, @RequestBody OperationsDetailsTDO details) { 
if (version == 1) 
{ 
    doForVersion1(); 
} 
else if (version == 2) 
{ 
    doForVersion2(); 
} 

} 

這將是難以管理,因爲每個功能會有不同的分支。爲了演示這個問題,如果我有一個自動生成文檔的工具 - 它將無法理解API是什麼。

其次,我不知道該怎麼處理綁定到JSON對象的類。我是否需要複製所有這些類,以進行較小的更改?

Thx。

+0

相關http://stackoverflow.com/questions/389169/best-practices-for-api-versioning – andyb

+0

畢竟這是一個不同的API。你必須改變使用它的任何東西。 –

回答

1

我同意你傳遞的版本作爲參數,就像

@RequestMapping(method = RequestMethod.POST, value = "/api/{version-var}/getData") 

但我不認爲這是添加大量分支機構的一個好主意, 我們要提取資源類的所有方法一個業務接口,比如,

private IDataRetrieve dataRetriever; 
@RequestMapping(method = RequestMethod.POST, value = "/api/{version-var}/getData") 
public @ResponseBody ResponseDataDTO createReleaseFromTemplate(@PathVariable("version-var") Integer version, @RequestBody OperationsDetailsTDO details) { 
    dataRetiever = DataRetrieverFactory.getDataTrieverByVersion(version); //TODO, create a factory to get DataRetriever 
    return dataRetiever.getData(); 
} 

然後你需要兩個入級實現IDataRetriver,(一爲V1,另一個用於V2);爲了避免重複的代碼,您可以爲V1和V2添加一個抽象類,並使用Template Patern刪除重複的代碼。

+0

+1我只是不太喜歡接口的'I'前綴。客戶不應該知道它使用的是接口或實現。 – Bart

+0

以及JSON對象呢?它們是根據相關類自動生成的。我需要複製這些類嗎? – Jonathan

+0

我不認爲我們必須重複這些類。 (「這些類」是指入口/視圖類,對吧?)。按照我的想法,v1/v2將包含一些業務邏輯,返回應該是相同的。如果v1不支持某種方法,只需拋出異常。 – Stony

0

如果您爲版本使用路徑變量(see here for example),則可以在RequestMapping中使用正則表達式。或者,您可以創建一個新方法,該方法只需調用舊方法,但具有較新的v2版本的RequestMapping。或者,創建一個通用方法來抓取版本並調用實際處理該請求版本的正確方法。最後一種方法的獎勵:如果發送的版本不受支持,例如發送/ app/v10 /任何內容,您可以獲取版本並向用戶發送特定錯誤。

+0

** a)**不需要正則表達式。那麼爲什麼要使用它? ** b)**隨着api版本數量的增長,遍佈各處的代碼將不易管理。 ** c)**您不能簡單地將一個版本轉儲到另一個版本。客戶正在使用這些API。 – Bart

+0

a)正則表達式可用於幫助匹配請求URL。這是OP所要求的b)沒有人說要複製代碼。他正在創造一個新的API,同時留下舊的。這將是新的代碼,對吧?我不認爲我提到的任何東西都需要和「重複代碼」c)沒有人說轉儲v1。我說過「你可以使用正則表達式,或者你可以在你的控制器中使用另一種v2方法,或者你可以將你的版本更改爲一個路徑變量,然後有一種方法,然後切換到所需版本的正確底層方法」 – CodeChimp

+0

順便說一下,我相信我最後提出的建議與@StonyZhang建議的類似,它使用版本作爲路徑變量來確定要調用哪個版本。我曾假設OP使用標準的OOP和MVC實踐,並且「服務層」將在某處。 – CodeChimp

相關問題