RESTful概述

一、來源


  • REST:Representational State Transfer (表象層狀態轉變)
    • 每一個URL代表一個資源
    • 客戶端和服務器之間,傳遞這種資源的某個表現層
    • 客戶端通過四個HTTP動詞(get、post、put、delete),對服務器資源進行操作,實現“表現層狀態轉化”

二、六大原則


1. C-S架構

  • 數據的存儲在Server端,Client端只需要使用就行。兩端徹底分離的好處使Client端代碼的可移植性變強,Server端的拓展性變強。兩端單獨開發,互不干擾

2. 無狀態性

  • http請求本身就是無狀態的,基於C-S架構,客戶端的每一次請求帶有充分的信息能夠讓服務端識別。請求所需的一些信息都包含在URL的查詢參數、header、body,服務端能夠根據請求的各種參數,無需保存客戶端的狀態,將響應正確返回給客戶端。無狀態的特徵大大提高了服務端的健壯性和可擴展性
  • 無狀態性也存在一點缺陷,客戶端每次請求都必須帶上相同重複的信息確定自己的身份和狀態,造成傳輸數據的冗餘性,但這種確定對於性能和使用來說,幾乎可以忽略不計

3. 統一的接口

  • REST架構的核心是統一的接口。客戶端只需要關注實現接口就可以,接口的可讀性加強,使用人員方便調用

4. 一致的數據格式

  • 服務端返回的數據格式要麼是xml,要麼是json,或者直接返回狀態碼。
  • 每一項數據都應該具備自我描述的信息,方便代碼處理和解析其中的內容。比如:通過http返回的數據裏有[MIME type]信息,從這個信息可以知道數據的具體格式。

5. 系統分層

  • 客戶端通常無法表明自己是直接還是間接與端服務器進行連接,分層是同樣要考慮安全策略

6. 可緩存

  • 在萬維網上,客戶端可以緩存頁面的響應內容。因此響應都應隱式或顯式的定義爲可緩存的,若不可緩存要避免客戶端在多次請求後舊數據或髒數據來響應。管理得當的緩存會部分地或完全地除去客戶端與服務端的交互,進一步改善性能和延展性。

7. 按需編碼、可定製代碼(可選)

  • 服務端可選擇臨時給客戶端下發一些功能代碼讓客戶端來執行,從而定製和擴展客戶端的某些功能。比如服務端可以返回一些 Javascript 代碼讓客戶端執行,去實現某些特定的功能。
    提示:REST架構中的設計準則中,只有按需編碼爲可選項。如果某個服務違反了其他任意一項準則,嚴格意思上不能稱之爲RESTful風格。

三、RESTful的7個最佳實踐


1. 版本

  • 將版本直接放到URL中,簡潔明瞭
        https://example.com/api/v1/
    

2. 參數命名規範

  • query parameter 採用駝峯或下劃線都可以
        https://example.com/api/users/today_login  獲取今天登錄的用戶
        https://example.com/api/users/today_login&sort=login_desc  獲取今天登錄的用戶並以降序排列
    

3. url命名規範

  • API命名應該按照約定俗成的方式,簡潔明瞭。在RESTful架構中,每個url代表一種資源所以url中不能有動詞,只能有名詞,並且名詞中也應該使用複數。實現者應使用相應的Http動詞GET、POST、PUT、PATCH、DELETE、HEAD來操作這些資源即可。
        不規範的的url,冗餘沒有意義,形式不固定,不同的開發者還需要了解文檔才能調用。
        https://example.com/api/getallUsers     GET 獲取所有用戶 
        https://example.com/api/getuser/1       GET 獲取標識爲1用戶信息 
        https://example.com/api/user/delete/1   GET/POST 刪除標識爲1用戶信息 
        https://example.com/api/updateUser/1    POST 更新標識爲1用戶信息 
        https://example.com/api/User/add        POST 添加新的用戶
        
        規範後的RESTful風格的url,形式固定,可讀性強,根據users名詞和http動詞就可以操作這些資源
        https://example.com/api/users GET 獲取所有用戶信息 
        https://example.com/api/users/1 GET 獲取標識爲1用戶信息 
        https://example.com/api/users/1 DELETE 刪除標識爲1用戶信息 
        https://example.com/api/users/1 Patch 更新標識爲1用戶部分信息,包含在body中 
        https://example.com/api/users POST 添加新的用戶
    

4. 統一返回數據格式

  • 對於合法的請求應該統一返回數據格式,以json爲例:
    • code:包含一個證書類型的HTTP相應的狀態碼
    • status:包含文本:“success”,"fail"或“error”。
      • 狀態碼在500-599爲“fail”
      • 狀態碼在400-499爲“error”
      • 其餘均爲“success”
    • message:當狀態值爲“fail”和“error”時有效,用於顯示錯誤信息。參照國際化標準,他可以包含信息碼或者編碼。
    • data:包含響應的body。當狀態值爲“fail”和“error”時,data僅包含錯誤原因或異常名稱、或者null也可以是
        成功返回的響應json格式
        {
            "code": 200,
            "message": "success",
            "data": {
                "username": "123456",
                "age": 16,
                "address": "Beijing"
            }
        }
        
        失敗返回的響應json格式
        {
            "code": 401,
            "message": "error message",
            "data": null
        }
    
    • 下面這個ApiResult的泛型類是在項目中用到的,拓展性強,使用方便。返回值使用統一的 ApiResult 或 ApiResult錯誤返回使用ApiResult.Error進行返回;成功返回,要求使用ApiResult.Ok 進行返回。
          public class ApiResult: ApiResult
              {
                  public new static ApiResult<T> Error(string message)
                  {
                      return new ApiResult<T>
                      {
                          Code = 1,
                          Message = message,
                      };
                  }
                  [JsonProperty("data")]
                  public T Data { get; set; }
              }
              public class ApiResult
              {
                  public static ApiResult Error(string message)
                  {
                      return new ApiResult
                      {
                          Code = 1,
                          Message = message,
                      };
                  }
          
                  public static ApiResult<T> Ok<T>(T data)
                  {
                      return new ApiResult<T>()
                      {
                          Code = 0,
                          Message = "",
                          Data = data
                      };
                  }
                  /// <summary>
                  /// 0 是 正常 1 是有錯誤
                  /// </summary>
                  [JsonProperty("code")]
                  public int Code { get; set; }
                  [JsonProperty("msg")]
                  public string Message { get; set; }
          
                  [JsonIgnore]
                  public bool IsSuccess => Code == 0;
              }
      
      

5. http狀態碼

  • 根據http status code就可以知道刪除、添加、修改等是否成功
    • 1** 請求未成功
    • 2** 請求成功、表示成功處理了請求的狀態碼
    • 3** 請求被重定向、表示要完成請求,需要進一步操作。通常,這些狀態碼用來重定向
    • 4** 請求錯誤這些狀態代碼出現錯誤,妨礙了服務器的處理
    • 5** 服務器錯誤,表示服務器在嘗試處理請求時發生內部錯誤。這些錯誤可能是服務器本身出錯,而不是請求出錯

6. 合理使用query parameter

  • 在請求數據時,客戶端經常對數據進行過濾和分頁等要求,而這些參數推薦採用HTTP Query Parameter的方式實現
        比如設計一個最近登陸的所有用戶
        https://example.com/api/users?recently_login_day=3
    
        搜索用戶,並按照註冊時間降序
        https://example.com/api/users?recently_login_day=3
    
        搜索用戶,並按照註冊時間升序、活躍度降序
        https://example.com/api/users?q=key&sort=create_title_asc,liveness_desc
    
    

7. 多表、多參數連接查詢如何設計URL

  • 示例:
        查詢一個獲取在6月份的訂單中大於500元的且用戶地址是北京,用戶年齡在22歲到40歲、購買金額降序排列的訂單列表
        
        https://example.com/api/order?order_mouth=6&order_amount_greater=500&address_city=Beijing&sort=order_amount_desc&age_min=20&age_max=40
        
        可以優化爲
        https://example.com/api/orders/beijing/6?order_amount_greater=500&sort=order_amount_desc&age_min=22&age_max=40
    
    
  • 再如博客園開放的Api獲取個人博客隨筆列表
        請求方式:GET 
        請求地址:https://api.cnblogs.com/api/blogs/{blogApp}/posts?pageIndex={pageIndex} 
        (ps:blogApp:博客名)
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章