你是小阿巴,剛入職的後端程序員,負責給前端的阿花提供 API 接口。

結果一週後,你被阿花揍得鼻青臉腫。
阿花:你是我這輩子見過接口寫的最爛的程序員!

你一臉委屈找到號稱 “開發之狗” 的魚皮訴苦:接口不是能跑就行嗎?

魚皮嘲笑道:小阿巴,你必須得學學 RESTful API 了。
你撓撓頭:阿巴阿巴,什麼玩意,沒聽説過!
⭐️ 推薦觀看視頻版,動畫更生動:https://bilibili.com/video/BV1WFBXBmExs
什麼是 RESTful API?
魚皮:首先,REST 的全稱是 REpresentational State Transfer,翻譯過來叫 “表現層狀態轉移”。
你一臉懵:魚皮 gie gie,能説人話嗎?我是傻子,聽不太懂。
魚皮:別急,我給你拆開來講,保證你理解。
RE(Representational) 表現層,是指 資源(Resource) 的表現形式。
你好奇了:什麼是資源?
魚皮:資源就是 你想要操作的數據對象。
比如用户、商品、文章,這些都是資源。用户列表是一個資源,某個具體的用户也是一個資源。

表現層是指資源呈現出來的具體格式,比如同一個用户資源,可以用 JSON 格式返回給客户端,也可以用 XML 格式返回,這就是不同的 “表現形式”。

S(State) 是指 “狀態”。
你:啥是狀態?
魚皮:比如你登錄網站後,服務器會在內存中記住 “你是誰”,之後在網站上操作就不用再次登錄了,這就是 有狀態。

而 無狀態(Stateless) 呢,就是服務器不記錄客户端的任何信息,每次請求都是獨立的。

你:哦哦哦,就像一個人去餐廳吃飯,服務員不記得他上次點了什麼,每次都要重新點單,這就是無狀態。

反過來,服務員記得他愛吃魚皮,這就是有狀態。

魚皮:沒錯,接下來是 T(Transfer) 轉移。
要注意,轉移是 雙向 的:
1)當你用 GET 請求時,服務器把資源的狀態(比如用户信息的 JSON 數據)轉移給客户端。

2)當你用 POST/PUT 請求時,客户端把資源的新狀態(比如新用户的信息)轉移給服務器,從而改變服務器上資源的狀態。

組合起來,REST(Representational State Transfer) 是一種 軟件架構風格,讓客户端和服務器通過統一的接口,以無狀態的方式,互相傳遞資源的表現層數據(比如 JSON),來查詢或者變更資源狀態。

而 ful 是個後綴,就像 powerful(充滿力量的)一樣,表示 “充滿...特性的”。
因此,RESTful API 是指符合 REST 架構風格的 API,也就是遵循 REST 原則設計出來的接口。
注意,它 不是協議、不是標準、不是強制規範,只是一種建議的設計風格。你可以遵循,也可以不遵循。

你撓了撓頭:説了一大堆,RESTful API 到底長啥樣啊?
魚皮:舉個例子,比如你要做個用户管理系統,對用户信息進行增刪改查,用 RESTful 風格的 API 就長這樣:
GET /users/123 獲取 ID 為 123 的用户
POST /users 創建新用户
PUT /users/123 更新用户 123
DELETE /users/123 刪除用户 123
你眼前一亮:哇,比我寫的整齊多了!

快帶我學一下 RESTful 的寫法吧,我要讓前端阿花刮目相看!

RESTful API 寫法
魚皮:好,很有志氣!接下來我會帶你一步步構造一個完整的 RESTful API。分為兩部分,客户端發送請求 和 服務端給出響應。
客户端請求
第一步:確定資源
資源用 URI(統一資源標識符)來表示。核心原則是:用名詞來表示資源,不用動詞。
具體來説,推薦用名詞複數表示資源集合,比如 /users 表示用户列表、/products 表示商品列表。
如果要操作 具體某個資源,就加上 ID,比如 /users/123 表示 ID 為 123 的用户。
資源還 支持嵌套,比如 /users/123/orders 表示用户 123 的所有訂單。
你想了想:那還可以更深層級麼?比如 /users/123/orders/456 表示用户 123 的訂單 456。

魚皮點點頭:你的理解完全正確,但不建議嵌套層級太深。
第二步:選擇動作
確定了資源後,接下來要選擇 動作,也就是你想怎麼處理這個資源。
RESTful API 主要通過不同的 HTTP 方法來表示增刪改查操作:
1)GET:查詢資源
-
GET /users查詢所有用户 -
GET /users/123查詢 ID 為 123 的用户
2)POST:創建資源
-
POST /users創建新用户
3)PUT:完整更新資源,需要提供資源的所有字段,多次執行結果相同(冪等性)
-
PUT /users/123完整更新用户 123
4)PATCH:部分更新資源,通常用於更精細的操作
-
PATCH /users/123只更新用户 123 的某些字段
5)DELETE:刪除資源
-
DELETE /users/123刪除用户 123

魚皮:到這裏,一個基本的 RESTful API 請求就構造完成了。
你:就這麼簡單?我不滿足,還有更高級的寫法嗎?
魚皮:當然~
第三步:添加查詢條件(可選)
有時候我們需要更精確地篩選數據,這時候可以加查詢參數,比如:
-
分頁:
/users?page=2&limit=10查詢第 2 頁,每頁 10 條用户數據 -
過濾:
/users?gender=male&age=25查詢性別為男、年齡 25 的用户 -
排序:
/users?sort=created_at&order=desc按創建時間倒序排列用户
你:等等,這查詢參數跟 RESTful 有啥關係?正常的請求不都是這麼寫嗎?
魚皮:確實,查詢參數本身不是 RESTful 特有的。但 RESTful 風格強調 把篩選、排序、分頁這些操作,都通過 URL 參數來表達:

而不是在請求體裏傳一堆複雜的 JSON 對象:

這樣一來,URL 更清晰,而且瀏覽器、CDN、代理服務器都能直接根據 URL 來緩存響應結果。比如 /users?page=1 和 /users?page=2 是兩個不同的 URL,可以分別緩存。但如果把參數放在請求體裏,URL 都是 /users,緩存就沒法區分了。

第四步:版本控制(可選)
隨着業務發展,接口可能需要升級。為了不影響老用户,可以在 URI 中標明版本:
-
/v1/users第一版用户接口 -
/v2/users第二版用户接口
這樣,老用户繼續用 v1,新用户用 v2,互不影響。

第五步:保持無狀態
此外,還記得我們前面講 REST 裏的 ST(State Transfer) 嗎?
RESTful 的核心原則之一是 無狀態(Stateless),客户端每次請求必須包含所有必要信息,服務器不記錄客户端狀態。
比如用户登錄後,不是讓服務器記住 “你已經登錄了”,而是每次請求都要帶上身份憑證(Token),像這樣:
GET /orders
Header: Authorization: Bearer xxx
這麼做的好處是,服務器不用記錄誰登錄了、誰沒登錄,每個請求都是獨立的。這樣一來,你想加多少台服務器都行,任何一台都能處理請求,輕鬆實現負載均衡和橫向擴展。

你點頭如搗蒜:怪不得我調用 AI 大模型 API 的時候,就要傳這個 Token!
服務端響應
魚皮:講完客户端請求,再來看服務器收到請求後,該怎麼響應?
主要注意 2 點:
1、統一響應格式
目前大多數 RESTful API 基本都用 JSON 格式,因為輕量、容易解析。
{
"id": 123,
"name": "小阿巴",
"email": "aba@codefather.cn"
}
但這並不是強制的,也可以用 XML、HTML 等格式。

2、返回合適的 HTTP 狀態碼
響應要帶上合適的狀態碼,讓客户端一眼看懂發生了什麼。

HTTP 狀態碼有很多,大體可以分為 5 類:
-
1xx 系列:信息提示(用得少,瞭解即可)
-
2xx 系列:成功
-
200 OK:請求成功,正常返回數據(用於 GET、PUT、PATCH)
-
-
3xx 系列:重定向
-
301 Moved Permanently:資源永久移動到新位置
-
302 Found:資源臨時移動
-
-
4xx 系列:客户端錯誤
-
400 Bad Request:請求參數格式錯誤
-
401 Unauthorized:未驗證身份,需要登錄
-
403 Forbidden:已認證但沒有權限訪問
-
404 Not Found:資源不存在
-
405 Method Not Allowed:請求方法不被允許
-
-
5xx 系列:服務器錯誤
-
500 Internal Server Error:服務器內部錯誤
-
502 Bad Gateway:網關錯誤
-
503 Service Unavailable:服務暫時不可用
-
504 Gateway Timeout:網關超時
-

你恍然大悟:懂了,以後前端看到 500,就知道是我後端的鍋;看到 400,就知道是她自己傳參傳錯了。誰也別想甩鍋!

魚皮點點頭:不錯,以上這些,就是 RESTful API 的基本寫法。你學會了嗎?
你:學廢了,學廢了!

魚皮:那我來考考你,下面哪個是標準的 RESTful API?
-
A.
GET /getUsers -
B.
GET /user/list -
C.
POST /users/query -
D.
GET /users/delete/123
你開心地怪叫起來:阿巴,肯定是 C 啊!

魚皮:錯,4 個全都不標準!
-
A 用了動詞
getUsers -
B 用了單數
user和動詞list -
C 用 POST 查詢,還帶了動詞
query -
D 用 GET 刪除,還帶了動詞
delete
你掉了根頭髮:原來這麼嚴格!

等等,你説 RESTful 不能用動詞,但有些操作不是標準的增刪改查啊,比如用户要支付訂單,該怎麼設計接口呢?是要用 POST /orders/123/pay?
魚皮搖頭:你已經很努力了,但 pay 是動詞。更標準的設計是把 “支付” 行為看作 創建 一個支付記錄,用名詞而不是動詞。
POST /orders/123/payments
比如這個請求,表示為訂單 123 創建一筆支付記錄。
你又掉了根頭髮:妙啊,怪不得説英語對學編程有幫助呢,我悟了,我悟了!

RESTful 的六大約束
魚皮:不錯,學到這裏你已經掌握了 RESTful 的 80%,能夠實際應用了。接下來的知識,你只需簡單瞭解一下,就能拿去和麪試官吹牛皮了。
比如很多同學都不知道,RESTful 其實有 6 個約束條件:
-
Client-Server(客户端-服務器分離):前後端各幹各的活,前端負責展示,後端負責數據處理,互不干擾。
-
Stateless(無狀態):每次請求都是獨立的,服務器不保存客户端的會話信息,所有必要信息都在請求中攜帶。
-
Cacheable(可緩存):服務器的響應可以被標記為可緩存或不可緩存,客户端可以重用緩存數據,減少服務器壓力,提升性能。
-
Layered System(分層系統):客户端不需要知道直接連的是服務器還是中間層,系統可以靈活地加代理、網關、負載均衡器等。
-
Uniform Interface(統一接口):所有資源都通過統一的接口訪問,降低理解成本,提高可維護性。
-
Code-On-Demand(按需代碼):可選項,服務器可以返回可執行代碼(比如 JavaScript)給客户端執行,但實際工作中很少用。

你直接聽懵了:阿巴阿巴,這麼多約束,我必須全遵守嗎?
魚皮:可以不用,RESTful 只是一種 API 的 建議風格。在實際工作中,很少有 API 能完美符合所有約束,大家可以靈活調整,甚至什麼接口都用 POST + 動詞 一把梭。只要團隊達成一致、用得舒服就行。

就像剛才那個支付訂單的例子,POST /orders/123/payments 雖然符合 RESTful 規範,但有同學會覺得 POST /orders/123/pay 更直觀易懂,也沒問題。
不過現階段,我建議你先養成遵循 RESTful 的好習慣,等積累了經驗,再根據實際情況靈活調整。
怎麼快速實現 RESTful API?
你:嗚嗚,但我只是個小阿巴,背不下來這些寫法,我怕自己寫着寫着就不規範了,怎麼辦啊?

魚皮:別擔心,有很多方法可以幫你快速實現和檢查 RESTful API。
1、使用開發框架
幾乎所有主流開發框架都支持 RESTful API 的開發,它們能幫你自動處理很多細節,比如:
-
Java 的 Spring Boot:通過
@GetMapping("/users")、@PostMapping("/users")等註解,你只需要寫一行代碼就能定義符合 RESTful 風格的路由。框架會自動把對象轉成 JSON、設置正確的 HTTP 狀態碼,你都不用操心。 -
Python 的 Django REST Framework:你只需要定義一個數據模型(比如 User 類),框架就能自動生成
GET /users、POST /users、PUT /users/123、DELETE /users/123這一整套 RESTful 接口,大幅減少代碼量。 -
Go 的 Gin :專門為 RESTful API 設計,語法非常簡潔。比如
router.GET("/users/:id", getUser)就能綁定一個 GET 請求,自動從 URL 中提取 ID 參數,還能通過路由分組把/api/v1/users和/api/v2/users輕鬆分開管理。
這些框架雖然不強制你遵循 RESTful,但用它們的特性,開發起來既輕鬆又規範,幫你省掉大量重複代碼。

2、使用 IDE 插件
比如 IDEA 的 RESTful Toolkit 插件,可以快速查看和測試接口。

還有 VSCode 的 REST Client 插件,可以直接在編輯器裏測試接口。

3、利用 AI 生成
RESTful 有明確的設計規範,而 AI 最擅長處理這種有章可循的東西!
比如直接讓 Cursor 幫你用 Spring Boot 寫一個用户管理的 RESTful API:

你只需要阿巴阿巴幾下,它就能生成規範的代碼。

4、生成接口文檔
寫完接口後,還可以用 Swagger 這類工具自動生成漂亮的接口文檔,直接甩給前端,對方一看就懂,還能在線測試接口,省去大量溝通成本。

你笑得像個孩子:這麼一看,RESTful API 不僅讓接口規範統一,還能提高開發效率,降低團隊溝通成本,前後端都舒服!爽爽爽!

魚皮點點頭:沒錯,這也是為什麼 RESTful 能成為業界主流的原因。
你:學會了學會了,我這就去重構所有接口,讓前端阿花刮目相看!

結尾
一週後,你把所有接口重構成了 RESTful 風格。
前端阿花打開新的接口文檔,眼睛亮了:小阿巴,你居然開竅了?!

你得意地笑了:那是,我可是學過 RESTful 的男人~ 阿花,晚上要不要一起?

阿花朝你吐了口唾沫:呸,你只不過學了一種 API 風格就得意洋洋。阿坤哥哥不僅精通 RESTful,還能手撕 GraphQL 和 gRPC 呢,你行麼?

你難受得不行:啥啥啥,這都是啥啊…… 魚皮 gie gie 快來救我!
