2011-11-25 70 views
15

鑑於REST風格的Web服務都是基於「一切都以資源形式表示,並且可以通過地址(URI)訪問」的神聖思想,這對於CRUD應用程序可能是有意義的(所有示例都是關於列出/創建/更新/刪除實體)。但是,其他業務邏輯如何創建一個與CRUD操作無關的簡單計算器RESTful服務呢? 對於這樣的REST服務,什麼是一個好的設計?如何創建一個RESTful計算器?

其次,如果SOAP的邏輯已經完全有意義,那麼使用REST over SOAP的真正優勢是什麼?

+0

那麼究竟是什麼問題呢? – paulsm4

回答

13

計算器服務可以很簡單地以REST風格進行建模。 「CRUD」中的「R」代表「閱讀」,沒有理由認爲「閱讀」也不意味着「計算」。因此,一個簡單的計算器Reverse Polish服務可以通過GET訪問:

GET https://calc.com/rpnCalc?3&4&%2B 
7 

上面簡單的URI方案增加了三個參數的GET請求:

3 
4 
+ (URL-encoded as %2B) 

這是一個冪等,安全和緩存的請求。如果這是一個非常複雜的數學查詢,需要花費很多時間來計算,我可以將這些查詢路由到一個開箱即用的HTTP代理,並使用它來立即返回任何預先計算的值,如果重複查詢同一個URI。

根據您需要執行的計算類型,您還可以向Calculator資源發送非常複雜的查詢(將查詢作爲請求正文傳遞),並且服務器可能會將URI返回到「result」資源,然後您可以通過GET來檢索結果,甚至通過它們進行分頁。

其次,如果SOAP的 邏輯已經完全有意義,那麼使用REST而不是SOAP會有什麼真正的優勢?

我可以使用像curl這樣的命令行工具訪問上述計算器服務,而無需構建複雜的SOAP片段。我可以在幾秒鐘內對它進行編碼,而無需使用任何第三方XML庫或SOAP工具包。我可以使用諸如HTTP代理的商品工具來緩存結果並提高性能。我不必擔心SOAP互操作性或檢查WS-I的兼容性。如果我正確使用超鏈接,那麼我可以改進和改進我的服務,而不會影響現有的客戶端或讓他們甚至重新編譯。沒有WSDL版本,也沒有我必須維護多年的易碎合約。客戶端已經知道GET/PUT/POST/DELETE做了什麼,我不必重新定義或重新記錄它們的語義。決定他們更喜歡JSON而不是XML的API客戶端可以使用HTTP內置的內容協商功能。我可以絕對使用SOAP和Web服務來完成這些事情的

嘿,如果SOAP符合你的需求,那就去吧。使用REST有許多好處,但它們可能不適合您的情況。至少,瞭解REST可以給你一本體面的書like this one,然後在獲得完整故事後讓你記住它。

+0

謝謝Brian!因此,如果方法也可以建模爲(子)資源,我也可以編寫「GET https://calc.com/arithmeticCalc/add?a=3&b=4」嗎? – karimyafi

+2

是的,但我會避免添加動詞到您的URI結構。你在HTTP中已經有了動詞,所以你應該使用名詞來描述你的URI中的資源。這樣你的API客戶端就不會對如何使用每個資源感到困惑。想象一下你爲一個'/ add'資源做了一個HTTP'POST' - 我怎麼知道它是否會實際添加或創建一個子資源?爲了避免您的示例中出現混淆,我會稍微將其更改爲'calc.com/arithmeticCalc/adder?a = 3&b = 4'。 –

2

這是REST中名詞和動詞之間張力很好的例子。建議使用「添加」或「加法器」作爲資源是非常幼稚的。這意味着每個操作都可以通過GET方式完成「加法器」或「減法器」。當然可以讓資源「計算」,但我們使用動詞。我們可以將它改爲「計算器」或「答案」,它們都是名詞,但我們確實沒有做任何有用的事情。

19

HTTP POST不一定需要創建持久性資源。在RFC 2616, section 9.5我們發現:

POST方法執行的動作可能不會導致資源 可以通過URI標識。在這種情況下,200(OK)或204 (無內容)是合適的響應狀態,具體取決於 是否包含描述結果的實體。

這意味着我們可以考慮「創建計算」而不必在其自己的URL中保留計算結果。您的API可能看起來像這樣:

Request: 
POST /calculations 
Content-Type: text/plain 

3 + 3/12^(3 * PI) 

Response: 
200 OK 
Content-Type: text/plain 

3.005454 

這樣做,你不及格「內容」通過URL的好處,當你嘗試通過客戶端或代理有限長度提交長的計算,這將打破對於網址。您也可以爲請求和回覆支持不同的表示。

3

這個問題已經有幾年了。但似乎仍然有一個讓我和很多同事感到困惑的問題。我們無法達成滿足每個人的解決方案。

但是對於一個簡單的計算器,我認爲下面的JAXRS實現提供了一個乾淨的API。

/** 
* This class defines a CalculatorResource. 
*/ 

@Path("v{version}/calculators/{id}") 
@Named 
public class CalculatorResource { 

    private final Long value; 

    public CalculatorResource() { 
     value = 0L; 
    } 

    public CalculatorResource(Long initialValue) { 
     this.value = initialValue; 
    } 

    @GET 
    public Long getValue() { 
     return value; 
    } 

    @Path("+{value}") 
    public CalculatorResource add(@PathParam("value") Long value) { 
     return new CalculatorResource(this.value + value); 
    } 

    @Path("-{value}") 
    public CalculatorResource subtract(@PathParam("value") Long value) { 
     return new CalculatorResource(this.value - value); 
    } 

    @Path("*{value}") 
    public CalculatorResource multiply(@PathParam("value") Long value) { 
     return new CalculatorResource(this.value * value); 
    } 

} 

利用這種系統的實現中,URI可以是易於閱讀式。

例如,/api/v1/calculators/mycalc/+ 9/-4/* 3/+ 10 會返回25.