REST(Representational State Transfer)是一種通過HTTP協(xié)議設(shè)計(jì)API的架構(gòu)風(fēng)格,用于構(gòu)建分布式系統(tǒng)中的網(wǎng)絡(luò)應(yīng)用程序。REST API(RESTful API)是基于這種設(shè)計(jì)風(fēng)格的應(yīng)用程序編程接口。其主要優(yōu)點(diǎn)是其極大的靈活性, 只要需要直接從服務(wù)器向Web應(yīng)用程序或站點(diǎn)的用戶提供數(shù)據(jù), 開發(fā)人員直接使用REST API即可實(shí)現(xiàn)。
REST API 的設(shè)計(jì)目的是創(chuàng)建簡(jiǎn)單、可伸縮、可維護(hù)且具有良好可讀性的接口, 以促進(jìn)客戶端和服務(wù)器之間的有效通信, 通過使用HTTP協(xié)議和一組統(tǒng)一的設(shè)計(jì)原則, REST API在實(shí)現(xiàn)上具備一些特定的屬性:
下面我將使用Go語(yǔ)言來設(shè)計(jì)一個(gè)REST API的服務(wù)端, 這里的模擬場(chǎng)景是通過服務(wù)端來對(duì)外提供文章的增、刪、查服務(wù), 文章的查詢方式包括兩種: 1.查詢服務(wù)器所有文章內(nèi)容。2.根據(jù)文章ID查詢某篇文章的內(nèi)容。
文章的屬性包括三個(gè)字段: 文章ID、文章標(biāo)題、文章內(nèi)容, 這里可以用一個(gè)結(jié)構(gòu)體表示:
type Article struct { ID string `json:"id,omitempty"` Title string `json:"title,omitempty"` Content string `json:"content,omitempty"`}
由于我們?cè)O(shè)計(jì)了四個(gè)功能接口, 將其轉(zhuǎn)換成接口代碼框架如下:
// 獲取所有文章接口func GetArticles(w http.ResponseWriter, r *http.Request) { ...}// 獲取單篇文章接口func GetArticle(w http.ResponseWriter, r *http.Request) { ...}// 創(chuàng)建文章接口func CreateArticle(w http.ResponseWriter, r *http.Request) { ...}// 刪除文章接口func DeleteArticle(w http.ResponseWriter, r *http.Request) { ...}
首先來實(shí)現(xiàn)獲取所有文章的接口, 具體參考代碼如下:
// 獲取所有文章func GetArticles(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") // 嘗試從緩存中獲取文章列表 if cachedArticles, found := articleCache.Load("all"); found { json.NewEncoder(w).Encode(cachedArticles) return } // 從原始數(shù)據(jù)源獲取文章列表 json.NewEncoder(w).Encode(Articles) // 將文章列表存入緩存 articleCache.Store("all", Articles)}
獲取所有文章首先是嘗試從緩存中獲取文章列表, 緩存cachedArticles這里實(shí)際是一個(gè)sync.Map類型的變量, 支持并發(fā)安全, 如果找到的話, 直接序列化成JSON的格式返回。如果緩存中沒有找到, 則從原始數(shù)據(jù)源中獲取文章列表(實(shí)際應(yīng)用中應(yīng)該是從數(shù)據(jù)庫(kù)中獲取)并序列化成JSON返回。并把該文章列表存入緩存之中。
接下來實(shí)現(xiàn)第二個(gè)接口,通過文章ID來查詢, 實(shí)現(xiàn)參考代碼如下:
// 獲取單篇文章func GetArticle(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") params := mux.Vars(r) // 嘗試從緩存中獲取單個(gè)文章 if cachedArticle, found := articleCache.Load(params["id"]); found { json.NewEncoder(w).Encode(cachedArticle) return } // 從原始數(shù)據(jù)源獲取單個(gè)文章 for _, article := range Articles { if article.ID == params["id"] { json.NewEncoder(w).Encode(article) // 將單個(gè)文章存入緩存 articleCache.Store(params["id"], article) return } } json.NewEncoder(w).Encode(&Article{})}
首先將傳入的ID參數(shù)在緩存中進(jìn)行查找, 找到則直接返回JSON數(shù)據(jù)。如果沒有找到則繼續(xù)在文章列表中查找, 并將單篇文章存入緩存。
創(chuàng)建文章接口參考代碼如下:
// 創(chuàng)建文章func CreateArticle(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var article Article _ = json.NewDecoder(r.Body).Decode(&article) Articles = append(Articles, article) // 清除所有文章緩存 articleCache.Delete("all") json.NewEncoder(w).Encode(Articles)}
創(chuàng)建文章列表需要注意的是, 這里為了維護(hù)緩存一致性,避免臟數(shù)據(jù), 對(duì)緩存進(jìn)行了清空, 以便下次GetArticles()時(shí)更新最新的緩存。
同理也不難實(shí)現(xiàn)刪除文章的接口:
// 刪除文章func DeleteArticle(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") params := mux.Vars(r) // 清除單個(gè)文章緩存 articleCache.Delete(params["id"]) for index, article := range Articles { if article.ID == params["id"] { Articles = append(Articles[:index], Articles[index+1:]...) break } } // 清除所有文章緩存 articleCache.Delete("all") json.NewEncoder(w).Encode(Articles)}
最后, 在main函數(shù)中, 我們需要往列表中添加一些數(shù)據(jù)來模擬服務(wù)端保存的文章數(shù), 并且定義四個(gè)接口的路由, 整體代碼如下:
package mainimport ( "encoding/json" "log" "net/http" "sync" "github.com/gorilla/mux")// Article 結(jié)構(gòu)體表示 API 中的數(shù)據(jù)模型type Article struct { ID string `json:"id,omitempty"` Title string `json:"title,omitempty"` Content string `json:"content,omitempty"`}// Articles 數(shù)組用于存儲(chǔ)文章數(shù)據(jù)var Articles []Articlevar articleCache sync.Map// 獲取所有文章func GetArticles(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") // 嘗試從緩存中獲取文章列表 if cachedArticles, found := articleCache.Load("all"); found { json.NewEncoder(w).Encode(cachedArticles) return } // 從原始數(shù)據(jù)源獲取文章列表 json.NewEncoder(w).Encode(Articles) // 將文章列表存入緩存 articleCache.Store("all", Articles)}// 獲取單個(gè)文章func GetArticle(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") params := mux.Vars(r) // 嘗試從緩存中獲取單個(gè)文章 if cachedArticle, found := articleCache.Load(params["id"]); found { json.NewEncoder(w).Encode(cachedArticle) return } // 從原始數(shù)據(jù)源獲取單個(gè)文章 for _, article := range Articles { if article.ID == params["id"] { json.NewEncoder(w).Encode(article) // 將單個(gè)文章存入緩存 articleCache.Store(params["id"], article) return } } json.NewEncoder(w).Encode(&Article{})}// 創(chuàng)建文章func CreateArticle(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var article Article _ = json.NewDecoder(r.Body).Decode(&article) Articles = append(Articles, article) // 清除所有文章緩存 articleCache.Delete("all") json.NewEncoder(w).Encode(Articles)}// 刪除文章func DeleteArticle(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") params := mux.Vars(r) // 清除單個(gè)文章緩存 articleCache.Delete(params["id"]) for index, article := range Articles { if article.ID == params["id"] { Articles = append(Articles[:index], Articles[index+1:]...) break } } // 清除所有文章緩存 articleCache.Delete("all") json.NewEncoder(w).Encode(Articles)}func main() { // 初始化數(shù)據(jù) Articles = append(Articles, Article{ID: "1", Title: "Article 1", Content: "Content 1"}) Articles = append(Articles, Article{ID: "2", Title: "Article 2", Content: "Content 2"}) // 創(chuàng)建路由器 router := mux.NewRouter() // 定義路由處理程序 router.HandleFunc("/articles", GetArticles).Methods(http.MethodGet) router.HandleFunc("/articles/{id}", GetArticle).Methods(http.MethodGet) router.HandleFunc("/articles", CreateArticle).Methods(http.MethodPost) router.HandleFunc("/articles/{id}", DeleteArticle).Methods(http.MethodDelete) // 啟動(dòng)服務(wù)器 log.Fatal(http.ListenAndServe(":8080", router))}
在本地運(yùn)行服務(wù)端, 服務(wù)端將在本地監(jiān)聽8080端口, 通過瀏覽器輸入: http://127.0.0.1:8080/articles, 該接口將獲取所有文章,如圖:
通過API接口通過文章ID查詢某一篇文章,接口請(qǐng)求如下:
新增一條新文章是POST請(qǐng)求, 這里主要通過Apifox發(fā)送POST請(qǐng)求,如圖:
從返回的結(jié)果來看, 成功添加了一條新記錄, 再次使用獲取全部文章接口看一下,如圖:
新記錄確實(shí)添加成功。
最后, 還是通過Apifox,我們發(fā)送一個(gè)刪除ID為2的文章請(qǐng)求,如圖:
從Apifox返回的結(jié)果來看,確實(shí)刪除成功了, 現(xiàn)在再獲取一下全部文章,如圖:
所有接口全部驗(yàn)證成功。
本文鏈接:http://www.www897cc.com/showinfo-26-56402-0.html用Go實(shí)現(xiàn)一個(gè)帶緩存的REST API服務(wù)端
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com