RESTful簡介


一、RESTful是什么?

RESTful架構,就是目前最流行的一種互聯網軟件架構。它結構清晰、符合標准、易於理解、擴展方便,所以正得到越來越多網站的采用。Fielding將他對互聯網軟件的架構原則,定名為REST,即Representational State Transfer的縮寫,翻譯出來就是“表層狀態轉化”。如果一個架構符合REST原則,就稱它為RESTful架構。要理解RESTful架構,最好的方法就是去理解Representational State Transfer這個詞組到底是什么意思,它的每一個詞代表了什么涵義。如果你把這個名稱搞懂了,也就不難體會REST是一種什么樣的設計。

1、資源(Resources)

REST的名稱"表現層狀態轉化"中,省略了主語。"表現層"其實指的是"資源"(Resources)的"表現層"。

所謂"資源",就是網絡上的一個實體,或者說是網絡上的一個具體信息。它可以是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的實在。你可以用一個URI(統一資源定位符)指向它,每種資源對應一個特定的URI。要獲取這個資源,訪問它的URI就可以,因此URI就成了每一個資源的地址或獨一無二的識別符。

所謂"上網",就是與互聯網上一系列的"資源"互動,調用它的URI。

2、表現層(Representation)

"資源"是一種信息實體,它可以有多種外在表現形式。我們把"資源"具體呈現出來的形式,叫做它的"表現層"(Representation)。

比如,文本可以用txt格式表現,也可以用HTML格式、XML格式、JSON格式表現,甚至可以采用二進制格式;圖片可以用JPG格式表現,也可以用PNG格式表現。

URI只代表資源的實體,不代表它的形式。嚴格地說,有些網址最后的".html"后綴名是不必要的,因為這個后綴名表示格式,屬於"表現層"范疇,而URI應該只代表"資源"的位置。它的具體表現形式,應該在HTTP請求的頭信息中用Accept和Content-Type字段指定,這兩個字段才是對"表現層"的描述。

3、狀態轉化(State Transfer)

訪問一個網站,就代表了客戶端和服務器的一個互動過程。在這個過程中,勢必涉及到數據和狀態的變化。

互聯網通信協議HTTP協議,是一個無狀態協議。這意味着,所有的狀態都保存在服務器端。因此,如果客戶端想要操作服務器,必須通過某種手段,讓服務器端發生"狀態轉化"(State Transfer)。而這種轉化是建立在表現層之上的,所以就是"表現層狀態轉化"。

客戶端用到的手段,只能是HTTP協議。具體來說,就是HTTP協議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。

它們分別對應四種基本操作:

  1. GET用來獲取資源,

  2. POST用來新建資源(也可以用於更新資源),

  3. PUT用來更新資源,

  4. DELETE用來刪除資源。

4、綜述

綜合上面的解釋,我們總結一下什么是RESTful架構:

  (1)每一個URI代表一種資源;

  (2)客戶端和服務器之間,傳遞這種資源的某種表現層;

  (3)客戶端通過四個HTTP動詞,對服務器端資源進行操作,實現"表現層狀態轉化"。

5、誤區

RESTful架構有一些典型的設計誤區。

1、一切皆資源,動作只是請求方式。

最常見的一種設計錯誤,就是URI包含動詞。因為"資源"表示一種實體,所以應該是名詞,URI不應該有動詞,動詞應該放在HTTP協議中。(get/put/post/delete)

舉例來說,某個URI是/posts/show/1,其中show是動詞,這個URI就設計錯了,正確的寫法應該是/posts/1,然后用GET方法表示show。

如果某些動作是HTTP動詞表示不了的,你就應該把動作做成一種資源。比如網上匯款,從賬戶1向賬戶2匯款500元,錯誤的URI是:

  POST /accounts/1/transfer/500/to/2

正確的寫法是把動詞transfer改成名詞transaction,資源不能是動詞,但是可以是一種服務:

  POST /transaction HTTP/1.1
  Host: 127.0.0.1
  
  from=1&to=2&amount=500.00

另一個設計誤區,就是在URI中加入版本號:

  http://www.example.com/app/1.0/foo

  http://www.example.com/app/1.1/foo

  http://www.example.com/app/2.0/foo

因為不同的版本,可以理解成同一種資源的不同表現形式,所以應該采用同一個URI。版本號可以在HTTP請求頭信息的Accept字段中進行區分(參見Versioning REST Services

  Accept: vnd.example-com.foo+json; version=1.0

  Accept: vnd.example-com.foo+json; version=1.1

  Accept: vnd.example-com.foo+json; version=2.0

二. RESTful API設計

  • API與用戶的通信協議,總是使用HTTPS協議

  • 域名 

    • https://api.example.com                         盡量將API部署在專用域名(會存在跨域問題)
    • https://example.org/api/                        API很簡單
  • 版本

    • URL,如:https://api.example.com/v1/
    • 請求頭跨域時,引發發送多次請求
  • 路徑,視網絡上任何東西都是資源,均使用名詞表示(可復數)

    • https://api.example.com/v1/zoos
    • https://api.example.com/v1/animals
    • https://api.example.com/v1/employees
  • method

    • GET      :從服務器取出資源(一項或多項)
    • POST    :在服務器新建一個資源
    • PUT      :在服務器更新資源(客戶端提供改變后的完整資源)
    • PATCH  :在服務器更新資源(客戶端提供改變的屬性)
    • DELETE :從服務器刪除資源
  • 過濾,通過在url上傳參的形式傳遞搜索條件狀態碼

    • https://api.example.com/v1/zoos?limit=10:指定返回記錄的數量
    • https://api.example.com/v1/zoos?offset=10:指定返回記錄的開始位置
    • https://api.example.com/v1/zoos?page=2&per_page=100:指定第幾頁,以及每頁的記錄數
    • https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回結果按照哪個屬性排序,以及排序順序
    • https://api.example.com/v1/zoos?animal_type_id=1:指定篩選條件
  • 錯誤處理,狀態碼是4xx時,應返回錯誤信息,error當做key。

 
        
{
    error: "Invalid API key"
}
 
        
  • 返回結果,針對不同操作,服務器向用戶返回的結果應該符合以下規范。

 
        
GET /collection:返回資源對象的列表(數組)
GET /collection/resource:返回單個資源對象
POST /collection:返回新生成的資源對象
PUT /collection/resource:返回完整的資源對象
PATCH /collection/resource:返回完整的資源對象
DELETE /collection/resource:返回一個空文檔
 
        

  

 
        
  • Hypermedia API,RESTful API最好做到Hypermedia,即返回結果中提供鏈接,連向其他API方法,使得用戶不查文檔,也知道下一步應該做什么。

  

{"link": {
  "rel":   "collection https://www.example.com/zoos",
  "href":  "https://api.example.com/zoos",
  "title": "List of zoos",
  "type":  "application/vnd.yourformat+json"
}}

 

  

 

三、基於Django實現

路由系統:

urlpatterns = [
    url(r'^users', Users.as_view()),
]
  

  

CBV視圖:

 
        
from django.views import View
from django.http import JsonResponse
 
class Users(View):
    def get(self, request, *args, **kwargs):
        result = {
            'status': True,
            'data': 'response data'
        }
        return JsonResponse(result, status=200)
 
    def post(self, request, *args, **kwargs):
        result = {
            'status': True,
            'data': 'response data'
        }
        return JsonResponse(result, status=200)

基於反射實現根據請求方式不同,執行不同的方法

原理:url-->view方法-->dispatch方法(反射執行其它方法:GET/POST/PUT/DELETE等等)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM