RESTful簡介

1、RESTful是什麼?

RESTful架構,就是目前最流行的一種互聯網軟件架構。它結構清晰、符合標準、易於理解、擴展方便,因此正獲得愈來愈多網站的採用。Fielding將他對互聯網軟件的架構原則,定名爲REST,即Representational State Transfer的縮寫,翻譯出來就是「表層狀態轉化」。若是一個架構符合REST原則,就稱它爲RESTful架構。要理解RESTful架構,最好的方法就是去理解Representational State Transfer這個詞組究竟是什麼意思,它的每個詞表明瞭什麼涵義。若是你把這個名稱搞懂了,也就不難體會REST是一種什麼樣的設計。html

一、資源(Resources)

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

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

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

二、表現層(Representation)

"資源"是一種信息實體,它能夠有多種外在表現形式。咱們把"資源"具體呈現出來的形式,叫作它的"表現層"(Representation)。跨域

好比,文本能夠用txt格式表現,也能夠用HTML格式、XML格式、JSON格式表現,甚至能夠採用二進制格式;圖片能夠用JPG格式表現,也能夠用PNG格式表現。數組

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

三、狀態轉化(State Transfer)

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

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

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

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

  1. GET用來獲取資源,

  2. POST用來新建資源(也能夠用於更新資源),

  3. PUT用來更新資源,

  4. DELETE用來刪除資源。

四、綜述

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

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

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

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

五、誤區

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

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

最多見的一種設計錯誤,就是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"
}}

 

  

 

3、基於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等等)

相關文章
相關標籤/搜索