深入理解 RESTful Api 架構

jopen 8年前發布 | 16K 次閱讀 WEB服務/RPC/SOA
一些常見的誤解

不要以為 RESTful Api  就是設計得像便于 SEO 的偽靜態,例如一篇博客資源 http://mengkang.net/blog/1 ,我們可以通過瀏覽器訪問該 URL 而讀取文章,但是這并不代表著它就是 RESTful Api 。

也不要認為URL 里有 queryString 就不是 RESTful Api ,例如 http://mengkang.net/blogs/?page=10&page_size=30

RESTful Api 與 SOAP Web API 在 URL 形式上的對比

從設計一個刪除評論的 api 說起 

我們可以這樣設計成類似于:

http://api.mengkang.net/?method=comment.del&id=x 

http://mengkang.net/comment/del/id/x 

或者其他形式的 url。


而 RESTful Api 則是:

[DELETE] http://mengkang.net/comments/1 


我們對比可以發現①和② URL 中,都有del的動作指示。

SOAP Web API采用RPC風格,它采用面向功能的架構,所以我們在設計SOAP Web API的時候首相考慮的是應高提供怎樣的功能(或者操作)。

而 RESTful Api 是面向資源的架構。是查詢、新增、修改、刪除,都該資源無關。

所以我們在③ URL 中沒有看到del的關鍵字,對比最為明顯。

進一步認識 RESTful Api 

我們知道 URL 全稱為“統一資源定位符(Uniform Resource Locator)”,用于描述 Web 資源所在的位置。RESTful Api 是以 HTTP 協議為強烈依托的,將類似于②這種以功能為主導的URL風格舍棄,還原 URL 的本質,它的宗旨就是一個 URL 就應該是一個資源,不能包含任何動作。

[POST]     http://mengkang.net/users   // 新增
[GET]      http://mengkang.net/users/1 // 查詢
[PATCH]    http://mengkang.net/users/1 // 更新
[PUT]      http://mengkang.net/users/1 // 覆蓋,全部更新
[DELETE]   http://mengkang.net/users/1 // 刪除

PUTPATCH的功能都可以代表更新,但略有不同,PUT大多時候表示更新該資源的全部信息,而PATCH則更新部分信息。

PUTPOST又一些功能的重疊,都可以是新建一個資源,POST時,新建資源的地址是由服務器返回給客戶端的。也就是說客戶端在發送POST請求資源之前還無法預知該資源的地址,這在我們的 Api 開發中非常常見,新建一個帖子,新建一條評論,都如此。

而資源的地址是客戶端預先知道的情況則比較少。也有人如此設計而使用PUT,比如需要對 github 上的某人的項目 star ,則可能會設計成:http://github.com/xxx/zhoumengkang/projectname/star 這里把“對這個項目已經點贊過”看成了一個資源,那么就可以用PUT,因為要刪除這個資源時,還是訪問這個 URL。

關于這些功能上有交集的地方,可能后面會有一些更加標準的規范或者協議吧。


最后說下HEADOPTIONSHEAD請求的是資源的元數據,比如一張照片,的元數據則可能包含了,照片拍攝的設備,地點,時間等。服務器一般將對應資源的元數據置于響應的報頭集合返回給客戶端,這樣的響應一般不具有主體部分。OPTIONS則是發送一種“探測”請求以確定針對某個目標地址的請求必須具有怎樣的約束(比如應該采用怎樣的HTTP方法以及自定義的請求報頭),然后根據其約束發送真正的請求。


關于是過濾篩選,排序和 token 等 query string 是支持使用,和唯一資源的概念不沖突。

Server 端代碼的基本設計思想

按照 RESTful Api 的規范,嚴格來說根據endpoint找到在 server 端映射成一個資源對象,例如通過 http://mengkang.net/users/1 找到UserResource對象

而在這個對象里對應著該資源支持的 Http 協議的方法。如果一個對象支持7種方式的請求,則類似于:

public class UserResource {

    private User user;

    public UserResource() {

    }

    public UserResource(int id) {
        //從數據查詢處該用戶的數據
        String name = "xxx";
        short age = 23;
        user = new User(id,name,age);
    }

    /**
     * 獲取單個用戶
     * 從 new UserResource(int) 開始
     * @return
     */
    public User get(){
        return user;
    }

    /**
     * 覆蓋用戶的全部信息
     * 從 new UserResource(int) 開始
     * @return
     */
    public boolean put(){
        return true;
    }

    /**
     * 只更新用戶的部分信息
     * 從 new UserResource(int) 開始
     * @return
     */
    public boolean patch(){
        return true;
    }

    /**
     * 創建一個 UserResource
     * @return
     */
    public int post(){
        return 1;
    }

    /**
     * 刪除用戶
     * @return
     */
    public boolean delete(){
        return true;
    }

}

如果有關注的 api 那么對于該用戶的 star 操作則應新建一個UserStarResource資源對象,因為每個資源最多只有這7中方法,構造方法除外,而不能有其他的相關的動作方法。

假如我們規定 URL 為 http://mengkang.net/user/1/star 表示是訪問者對 id 為 1 的這個用戶的 star 狀態的一個資源。(當前訪問者的信息通過 query string 傳遞 auth token 的形式獲取)

public class UserStarResource {

    public boolean get(){
        return true;
    }

    public boolean post(){
        return true;
    }
    public boolean delete(){
        return true;
    }
}

一個基于 netty 的輕量級的高性能的 RESTful Api Server https://github.com/zhoumengkang/netty-restful-server 

更多更詳細的信息可以閱讀下面兩篇文章

http://www.cnblogs.com/artech/p/restful-web-api-02.html

http://www.ruanyifeng.com/blog/2014/05/restful_api.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!