【Spring Boot】第2課-認識 RESTful API 與前後端的資料交換
本文最後更新於:2025-03-22
在認識前端與後端的差別後,本文將介紹它們之間的溝通媒介,即 Web API,其中又以 RESTful API 的類型最為常見。另外也會介紹查詢字串、負載(payload)、標頭及 HTTP 狀態碼,這些都是前後端所交換的資料。最後透過 Postman 這項工具,存取實際的 API。
若讀者未曾接觸後端領域,建議先從本文建立 Web API 的觀念。如此在第 3 課開始撰寫 Spring Boot 程式,以及工作時設計 API 時,才能更加得心應手。
一、什麼是 API
API 的全名是「Application Program Interface」,中文為「應用程式介面」,它定義了軟體之間的互動方式。
從廣義的角度來看,即便只是程式中寫好的一個方法(method),我們都能視為一個 API。畢竟它定義了應傳入的參數,以及回傳的值,讓我們知道如何使用。
以生活情境來比喻,我們到餐廳點餐,菜單就像是 API。雖然每家餐廳的菜單格式都長得不一樣,但只要客人會填寫,而店員或廚房也看得懂客人的點餐,整個流程便能正常進行。
如果放在前端發出請求(request),後端給予回應(response)的話題上,則 API 就是定義前端如何傳遞資料給後端,而後端又會回傳什麼結果。我們用「Web API」來稱呼。
在工作上,前端與後端的同事只要事先制定好 API,就能分頭在各自的程式專案進行開發了,雙方的程式碼也不會混在一起形成雜亂。這種做法稱為「前後端分離」,是業界工程師們推崇的模式。
二、RESTful API
REST 的全名為「Representational State Transfer」,中文為「表現層狀態轉換」。它是一種 Web API 的設計風格,將網路上的東西都視為「資源」,並且有不同的操作方式。
(一)HTTP 請求方法
當使用者發出請求,意味著要對某種東西進行操作,比方說取得產品或新增使用者。操作的方式包含新增、取得、更新、刪除等,如同資料庫的操作也有 CRUD。
HTTP 協定以這個概念為基礎,定義了「請求方法」,常見的方法如下。
- GET:取得資源。
- POST:新增資源。或是一個不容易歸類在其他方法的動作,例如登入。
- PUT:更新整個資源,也就是覆寫。
- PATCH:更新資源的一部份。
- DELETE:刪除資源。
(二)表示方式
RESTful API 是以「動詞 + 資源」這個想法為出發點,也就是 HTTP 請求方法加上資源的位置。而資源位置的表達方式就像網址,我們以「端點」(endpoint)來稱呼它。
假設社群網站上有篇文章的編號是「P1」,那麼這項資源在網路上的位置,可能就會被設計成 https://social.com/articles/P1
。此時搭配各種 HTTP 請求方法,即可組合出 RESTful API,表現出不同的意義。以下是一些範例。
- GET /articles/P1:取得編號為 P1 的文章。
- PUT /articles/P1:更新編號為 P1 的文章。
- DELETE /articles/P1:刪除編號為 P1 的文章。
- POST /articles:新增文章。
- GET /articles:取得所有文章。
其中「新增文章」的 API 是沒有編號的。從語意上,已經足夠表達出要在「articles」的路徑下新增資源了。
同理,「取得所有文章」的 API 也意味著取得 articles 路徑下的所有資源。但實際開發上通常不會真的回傳 DB 中的所有資料給前端啦,應該會限制一個範圍才對。例如某個人的所有文章、某個分類的所有文章、最新的 30 篇文章等。
最後要提醒讀者的是,RESTful 並非一套要遵守的標準。只是鼓勵開發者在設計時可以參考此風格,縮短大家認知上的差異。
三、在 API 攜帶資料
前端在呼叫 API 時,可以攜帶資料給後端,而後端同樣也能回傳資料,就像在交換一樣。
以上述的 RESTful API 為例子,新增文章時勢必要傳遞內容給後端吧!又或者是想查看某人的文章,也要將這項條件告訴後端。而取得文章時,則從後端得到對應的資料。本節將介紹攜帶資料的方式。
(一)查詢字串(query string)
查詢字串是呼叫後端 API 時,在端點後方所攜帶的資料。舉例來說,在論壇 Dcard 查看科技業板的最新文章之列表,瀏覽器的網址是這樣:
「https://www.dcard.tw/f/tech_job?tab=latest」。
其中「?」符號後方的就是查詢字串,它只有「tab=latest」一筆資料,代表最新的意思。
又或者是在 YouTube 觀看一部影片,瀏覽器的網址大概長這樣:
「https://www.youtube.com/watch?v=u6FcPuCs57o&=80s」。
其包含「v=u6FcPuCs57o」與「t=80s」兩筆資料,分別代表影片編號與開始播放的秒數。它們之間用「&」符號隔開。
(二)負載/酬載(payload)
負載(又稱酬載)在維基百科的解釋是:「資料傳輸中所欲傳輸的實際資訊,通常也被稱作實際資料或者資料體」。在本文,我們可以理解成前後端之間傳遞資料的「主要內容」。
前端發出請求時的 payload,亦可稱作「request body」;而後端給予回應時的 payload,也能稱為「response body」。
那麼所要傳遞的資料,應該如何提供呢?使用 JSON 和 XML 格式來表示,是較為常見的做法。筆者會以 JSON 為例來說明。
JSON 的英文全名是「JavaScript Object Notation」,是將資料寫成 Java Script 物件的樣子。以下是一份 JSON 格式的範例資料。
{
"title": "這是文章標題",
"content": "這是文章內容",
"tag": ["閒聊", "程式"],
"like": {
"isLiked": true,
"count": 28
}
}
JSON 資料的內容,都是以 欄位: 值 的格式來撰寫。而物件寫成大括弧,陣列寫成中括弧。
(三)標頭(header)
標頭是用來存放一些輔助資訊。以生活情境來比喻,header 彷彿信封袋上寫的資料,而 payload 則是信件內容。在 header 所能提供的資料,是有一套標準存在的。就像信封袋會寫郵遞區號、地址和收件人。
根據 header 是由前端還是後端所提供,又可分別稱呼為「request header」與「response header」。
以下舉例幾種 header。
- Content-Type:Payload 內容的格式。如 application/json、image/jpeg、text/html、multipart/form-data 等。
- Location:資源的端點。比方說建立新資源後,後端可回傳此標頭,提供該資源的路徑。
- Authorization:身份認證資訊。向後端發出請求時可攜帶,就像是出示識別證一樣。
四、HTTP 狀態碼
當後端進行回應時,會用一組數字來「概略」表達結果,稱為狀態碼。前端可以簡單地從狀態碼,判斷自己下一步該做什麼事,而未必要去取用 payload 的內容。
狀態碼的第一個數字會在 1 ~ 5 之間,藉此分為五大類型。後端會在不同的狀況,使用不同的狀態碼。除了 1 系列幾乎沒人在用之外,筆者挑出一些常見的,在以下分別介紹。
(一)2 系列(成功)
狀態碼 | 意義 | 說明 |
---|---|---|
200 | OK | 單純表示成功,是一種泛用的選擇。 |
201 | Created | 資源已經建立完成。後端可進一步在「Location」標頭提供該資源的端點,讓前端搭配 GET 請求方法取得該資料。 |
204 | No Content | 伺服器成功處理請求,只是回傳的 payload 沒有內容罷了。例如「按讚」這項簡單的功能,若 API 不需要回傳 payload,則不妨採用此狀態碼。 |
(二)3 系列(重導向)
狀態碼 | 意義 | 說明 |
---|---|---|
301 | Moved Permanently | 該資源已經永久被移動到另一個地方。建議後端在「Location」標頭提供該資源的新端點。會用到此狀態的場合,可能是網頁搬家,或是端點的設計更新了(例如網址上多了一個「v2」的階層,代表版本 2)。 |
304 | Not Modified | 用於快取機制。假設前端先前有將某資源快取在本地,那麼若嘗試再取得資源,後端可透過此狀態,通知前端該資源的內容並未更新過,請繼續用快取的資料即可。此機制需搭配數個 header 來實作,本文不贅述。 |
(三)4 系列(客戶端錯誤)
代表前端發送的資料有問題。
狀態碼 | 意義 | 說明 |
---|---|---|
400 | Bad Request | 發送請求時所攜帶的資料有明顯錯誤。例如 email 格式不正確、價格是負數等。 |
401 | Unauthorized | 沒有通過身份認證,所以後端不允許使用該 API。例如沒有登入某社群網站,就無法查看裡面的任何文章。 |
403 | Forbidden | 即便完成身份認證,但沒有權限存取該資源。例如已經登入某社群網站,但我不是某篇文章的分享對象,所以無法觀看。 |
404 | Not Found | 該資源不存在。例如試圖透過編號取得一篇不存在的文章。 |
422 | Unprocessable Entity | 前端發送請求,單看資料內容的話是沒問題(未被判為 400),但後端處理時才發現這份資料並不符合情境。例如下單購買商品時,前端發送「以歐元付款」,結果後端發現賣方不接受這個幣別(參考資料)。 |
(四)5 系列(服務端錯誤)
代表後端在處理請求時發生問題。
狀態碼 | 意義 | 說明 |
---|---|---|
500 | Internal Server Error | 後端程式可能發生例外(exception),例如 NullPointerException 或是連不到資料庫之類的。若無更適當的狀態碼,一般狀況均可選擇這種泛用的。 |
503 | Service Unavailable | 代表雖然後端程式仍在運行,但因為一些原因(例如流量太大、正在維護),暫時無法提供服務了。 |
504 | Gateway Timeout | 後端處理請求的時間過久。然而前端一直在等待回應,不能丟著不管,故可回傳此狀態碼進行告知。 |
五、API 測試工具
最後介紹一款叫做「Postman」的工具,它能讓我們在沒有前端的情況下,存取後端提供的 Web API。
一般來說,生活中使用各種軟體都是透過操作前端畫面來存取後端 API。但有時只是想「試用」API,當下並沒有對應的前端去配合。那麼利用這類工具,我們就能發送請求,傳送自己想要的資料,藉此測試 API 的效果。
以下兩個操作範例,是「Reqres」網站免費提供的 API 測試資料。不需註冊,讀者直接使用即可。
下圖是發出 GET 請求,並搭配查詢字串。
下圖是發出 POST 請求,並傳送 JSON 格式的 payload。
從操作畫面的右方,也能看見耗時與 HTTP 狀態碼。將「Body」的下拉式選單打開,還能切換查看 response header。