Spring?Cloud?零基礎實戰(zhàn)(六):Rest Api 開發(fā)

0黑忱、REST介紹

還是先從百度百科的 rest 詞條開始吧!


百度百科的 rest 詞條

正因為 REST 是目前比較流行的軟件架構江锨,所以網(wǎng)上有大量介紹及開發(fā)設計規(guī)范等的文章贞言,而我此篇文章基于實戰(zhàn)的目的斜棚,對 REST 關鍵的幾個方面做一個簡單的總結,當然和網(wǎng)上的其它文章一樣该窗,都是仁者見仁弟蚀、智者見智,僅供參考酗失!
本文將從下面幾個方面入手:

  • URI命名
  • HTTP方法
  • HTTP 狀態(tài)碼
  • 返回數(shù)據(jù)封裝格式
  • 接口文檔

1义钉、 URI 命名

1.1、命名規(guī)范

RFC 3986 定義了通用的URI語法:
URI = scheme “://” authority “/” path [ “?” query ][ “#” fragment ]
scheme: 指底層用的協(xié)議规肴,如http捶闸、https夜畴、ftp
host: 服務器的IP地址或者域名
port: 端口,http中默認80
path: 訪問資源的路徑删壮,就是咱們各種web 框架中定義的route路由
query: 為發(fā)送給服務器的參數(shù)
fragment: 錨點贪绘,定位到頁面的資源,錨點為資源id

  • 網(wǎng)址中只能有名詞央碟,不能用動詞
    在 RESTful 架構中税灌,每個網(wǎng)址代表一種資源( resource ),所以網(wǎng)址中不能有動詞亿虽,只能有名詞(特殊情況可以使用動詞)菱涤,而且所用的名詞往往與數(shù)據(jù)庫的表格名對應
    示例:
// 正確規(guī)范:
/users // 表示列舉所有用戶

// 錯誤規(guī)范:
/listUsers   // 有動詞
/getUsers    // 有動詞
  • 不用大寫
// 正確規(guī)范:
/users

// 錯誤規(guī)范:
/Users   // URI 不能有大寫字母
  • 用中杠 - 不用下杠 _
// 正確規(guī)范:
/user-orders // 用戶訂單列表

// 錯誤規(guī)范:
/user_orders // 不使用下劃線 _
  • URI 中的名詞表示資源集合,使用復數(shù)形式
// 正確規(guī)范:
/users                 // 復數(shù)表示集合
/users/1               // id 為 1 的用戶信息
/users/1/orders        // id 為 1 的用戶的訂單列表

錯誤規(guī)范:
/user                 // 不能用單數(shù)表示單個資源洛勉,需要用 id 來指定粘秆,參考 /user/1
  • 避免層級過深的 URI
    過深的 URI 不易維護,如 /users/1/orders/2/products/3 收毫,盡量使用查詢參數(shù)代替路徑中的實體導航攻走,如 /products?user=1&order=1;
  • API 版本號要放入到 URI 中
// 正確規(guī)范:
/v1/users    // 表示 API 版本為 v1
  • URL結尾不應該包含斜杠“/”
    REST API不允許一個尾部的斜杠牛哺,不應該將它們包含在提供給客戶端的鏈接的結尾處陋气。
// 錯誤規(guī)范:
/v1/users/   // 末尾不能為“/”
  • 資源過濾
    在獲取資源的時候,有可能需要獲取某些“過濾”后的資源引润,例如指定前10行數(shù)據(jù),如:
    http://api.test.com/v1/users?page=1&page-size=10
    下面是一些常用的過濾參數(shù):
    ?limit=10:指定返回記錄的數(shù)量
    ?offset=10:指定返回記錄的開始位置痒玩。
    ?page=2&per_page=100:指定第幾頁淳附,以及每頁的記錄數(shù)。
    ?sortby=name&order=asc:指定返回結果按照哪個屬性排序蠢古,以及排序順序实幕。
    ?animal_type_id=1:指定篩選條件

1.2类嗤、編寫代碼

為了簡化,我們采用前面編寫的演示工程的基礎上進行代碼編寫。
用 Idea 打開 edu 演示工程冰评,打開控制器 UseController 的代碼:


定位到 UserController 代碼

查、增默刚、改引几、刪,四個基本操作

上圖四個框內(nèi)的代碼分別對應查嘱丢、增薪介、改、刪四個操作的代碼越驻,下面進行 URI 規(guī)范的修改

  • 增加版本
    在都拿頂部的 @RestController 注解后面增加 @RequestMapping 注解汁政,該注解對 UserController 控制器的所有 http 方法都起作用道偷。假設 API 版本為 v1,修改結果如下:
    為 UserController 控制器添加版本

1.2.1记劈、修改“查詢” URI

  • 修改“查詢” URI
    修改前

    上圖中勺鸦, @GetMapping 注解表示 http 方法為 GET ,注解的值為“/list"目木,不規(guī)范换途,改為"/users"。
    修改后
  • 測試
    運行項目 UserApplication嘶窄,用 Postman 測試訪問怀跛,采用 GET 方法:
    測試:查詢數(shù)據(jù) - GET 方法

    OK!

1.2.2柄冲、修改“增加” URI

  • 修改“增加” URI

    修改前

    上圖中吻谋, @PostMapping 注解表示 http 方法為 POST ,注解的值為“/addUser"现横,不規(guī)范漓拾,改為"/users"。
    修改后

  • 測試
    重新運行 UserApplication 戒祠,用 Postman 測試訪問骇两,采用 POST 方法,并傳遞 username 和 password 兩個參數(shù):

    測試:增加數(shù)據(jù) - POST 方法

1.2.3姜盈、修改“修改” URI

  • 修改“修改” URI
    修改前

    上圖中低千, @PutMapping 注解表示 http 方法為 PUT ,注解的值為“/updUser/{id}"馏颂,不規(guī)范示血,改為"/users/{id}"。
    修改后
  • 測試
    重新運行 UserApplication 救拉,用 Postman 測試訪問难审,采用 PUT 方法,并傳遞 username 和 password 兩個參數(shù):
    測試:修改數(shù)據(jù) - PUT方法

    OK亿絮!

1.2.4告喊、修改“刪除” URI

  • 修改“刪除” URI
    修改前

    上圖中, @DeleteMapping 注解表示 http 方法為 DELETE派昧,注解的值為“/delUser/{id}"黔姜,不規(guī)范,改為"/users/{id}"斗锭。
    image.png
  • 測試
    重新運行 UserApplication 地淀,用 Postman 測試訪問,采用 DELETE 方法:
    測試: 刪除數(shù)據(jù) - DELETE 方法

    OK岖是!

2帮毁、HTTP方法

常用的方法有 GET , POST , PUT , DELETE 实苞,此外有時還會用到HEAD、PATCH和OPTION烈疚。前面說我們系統(tǒng)的設計是以資源為核心的黔牵,URI的命名要使用名詞,那我們要如何來表示一個操作動作呢爷肝?就是依靠HTTP方法猾浦,也叫HTTP動詞。也就是通過這種動名詞的組合來表示一次操作灯抛。
從上面修改 URI 的示例里金赦,已經(jīng)基本講述和測試了 GET , POST , PUT , DELETE 四種方法:
GET - 獲取數(shù)據(jù)集合,用到的 URI 為:/v1/users
POST - 新增數(shù)據(jù)对嚼,用到的 URI 為:/v1/users夹抗,和 GET 方法的 URI 相同
PUT - 修改數(shù)據(jù),用到的 URI 為:/v1/users/{id}
DELETE - 刪除數(shù)據(jù)纵竖,用到的 URI 為:/v1/users/{id}漠烧,和 PUT 方法的 URI 相同
通過列舉這四種方法,可以看到靡砌,采用規(guī)范后的 URI 已脓, 簡單、明晰了很多通殃!
注:其它 http 方法用得很少度液,如果有興趣可自行搜索及練習,此處不再贅述画舌!

3恨诱、HTTP 狀態(tài)碼

服務器向用戶返回的狀態(tài)碼和提示信息,常見的有以下一些(方括號中是該狀態(tài)碼對應的HTTP動詞)骗炉。

  • 200 OK - [GET]:服務器成功返回用戶請求的數(shù)據(jù),該操作是冪等的(Idempotent)蛇受。
  • 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數(shù)據(jù)成功句葵。
  • 202 Accepted - [*]:表示一個請求已經(jīng)進入后臺排隊(異步任務)
  • 204 NO CONTENT - [DELETE]:用戶刪除數(shù)據(jù)成功。
  • 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發(fā)出的請求有錯誤兢仰,服務器沒有進行新建或修改數(shù)據(jù)的操作乍丈,該操作是冪等的。
  • 401 Unauthorized - [*]:表示用戶沒有權限(令牌把将、用戶名轻专、密碼錯誤)。
  • 403 Forbidden - [*] 表示用戶得到授權(與401錯誤相對)察蹲,但是訪問是被禁止的请垛。
  • 404 NOT FOUND - [*]:用戶發(fā)出的請求針對的是不存在的記錄催训,服務器沒有進行操作,該操作是冪等的宗收。
  • 406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式漫拭,但是只有XML格式)。
  • 410 Gone -[GET]:用戶請求的資源被永久刪除混稽,且不會再得到的采驻。
  • 422 Unprocesable entity - [POST/PUT/PATCH] 當創(chuàng)建一個對象時,發(fā)生一個驗證錯誤匈勋。
  • 500 INTERNAL SERVER ERROR - [*]:服務器發(fā)生錯誤礼旅,用戶將無法判斷發(fā)出的請求是否成功。
    更多 HTTP 狀態(tài)碼洽洁,請到網(wǎng)上搜索痘系。

4、返回數(shù)據(jù)封裝格式

RestAPI 返回的封裝格式有很多種诡挂,網(wǎng)上也分化出很多陣營碎浇,公說公有理、婆說婆有理璃俗,所以還是要自己多練習奴璃、感受,做出和項目規(guī)模適應的封裝格式城豁。

  • 最簡格式
    我們剛才在例子里用的就是最簡格式苟穆,對于調(diào)試或較簡單的接口,可以這么用唱星,但不推薦雳旅。
[
    {
        "id": 1,
        "username": "金庸",
        "password": "123456"
    },
    {
        "id": 2,
        "username": "古龍",
        "password": "654321"
    }
]
  • 自定義業(yè)務狀態(tài)碼封裝格式
    該模式和業(yè)務聯(lián)系緊密,可靈活定制间聊,推薦攒盈。
{
    "status": 0,
    "message": "操作成功!",
    "data": [
        {
            "id": 1,
            "username": "金庸",
            "password": "123456"
        },
        {
            "id": 2,
            "username": "古龍",
            "password": "654321"
        }
    ],
    extra: {
        type: 1,
        desc: "附加操作"
    }
}
  • http 狀態(tài)碼 + 自定義業(yè)務狀態(tài)碼封裝形式
    該模式分為兩層狀態(tài)碼哎榴,最外層是 http 狀態(tài)碼型豁,里面一層是自定義業(yè)務狀態(tài)碼。在 http rest 模式下尚蝌,該數(shù)據(jù)封裝形式既可以滿足 http 狀態(tài)碼的統(tǒng)一性迎变,有可以兼顧到業(yè)務邏輯狀態(tài)碼的靈活定制、描述的準確性飘言。我更推薦使用該模式衣形。
{
    "code": 200,
    "msg": "OK",
    {
        "status": 0,
        "message": "操作成功!",
        "data": [
            {
                "id": 1,
                "username": "金庸",
                "password": "123456"
            },
            {
                "id": 2,
                "username": "古龍",
                "password": "654321"
            }
        ],
        extra: {
            type: 1,
            desc: "附加操作"
        }
    }
}

5姿鸿、 API 接口文檔

在此谆吴,我們將使用 Springfox(Swagger) 來實現(xiàn) ApiDoc 接口文檔倒源, Springfox 的前身是 Swagger-SpringMVC ,是一個開源的 API doc 框架纪铺,可以將我們的Controller的方法以文檔的形式展現(xiàn)相速,基于Swagger。官網(wǎng)地址:http://springfox.github.io/springfox/
下面我們繼續(xù)在演示項目 edu 上面來進行 API 接口文檔的實現(xiàn)鲜锚,如果這是您沒看本系列前面的文章突诬,請快速瀏覽一下前面的文章。

5.1芜繁、增加 Maven 依賴

我們在 microsvc 項目的 pom.xml 文件里添加下面的依賴:

<!--springfox-->
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.4.0</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.4.0</version>
</dependency>
在 microsvc 項目 pom.xml 文件中添加 swagger 依賴

5.2旺隙、修改 user 微服務的啟動程序文件 - UserApplication.java

import 導入:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.context.request.async.DeferredResult;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

添加注解:

@EnableSwagger2

在啟動類 UserApplication 里的 main 函數(shù)后面添加下面的代碼:

    @Bean
    public Docket userApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("user")
                .genericModelSubstitutes(DeferredResult.class)
                //  .genericModelSubstitutes(ResponseEntity.class)
                .useDefaultResponseMessages(false)
                .forCodeGeneration(false)
                .pathMapping("/")
                .select()
                .paths(PathSelectors.regex("/v1.*"))//過濾的接口
                .build()
                .apiInfo(userApiInfo());
    }

    private ApiInfo userApiInfo() {
        Contact contact = new Contact("檀布施", "https://www.baidu.com", "tanbushi@qq.com");
        ApiInfo apiInfo = new ApiInfo("用戶 API 接口",//大標題
                "用戶 REST 風格 API",//小標題
                "v1",//版本
                "www.baidu.com",
                contact,//作者
                "主頁",//鏈接顯示文字
                ""http://網(wǎng)站鏈接
        );
        return apiInfo;
    }

修改完成后,文件內(nèi)容如下圖:


UserApplication 的內(nèi)容

5.3骏令、修改 user 微服務的控制器文件 - UserController.java

import 導入:

import com.tanbushi.edu.microsvc.user.entity.UserEntity;
import com.tanbushi.edu.microsvc.user.repository.UserRepository;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

在 UserController 類里的每一個 mapping 后面追加一句蔬捷,下圖紅框里的內(nèi)容:


UserController 內(nèi)容修改
    @GetMapping(value = "/users")
    @ApiOperation(value = "獲取用戶列表", notes = "獲取當前條件下的用戶列表", produces = "application/json")
    @PostMapping(value = "/users")
    @ApiOperation(value = "添加用戶記錄", notes = "添加一條用戶記錄,username榔袋、password 必填", produces = "application/json")
    @PutMapping(value = "/users/{id}")
    @ApiOperation(value = "修改用戶記錄", notes = "修改一條用戶記錄周拐,usernme、password必填", produces = "application/json")
    @DeleteMapping(value = "/users/{id}")
    @ApiOperation(value = "刪除用戶記錄", notes = "刪除一條用戶記錄", produces = "application/json")

5.4凰兑、運行

重新編譯運行 UserApplication妥粟,成功后,在瀏覽器里輸入:http://127.0.0.1:8100/swagger-ui.html吏够,可以訪問到 API 文檔了:

API doc 界面

點擊紅框內(nèi)的 user-controller勾给, 就可以看的具體的接口說明了:
接口說明

6、其它

  • 消息體格式 - 推薦盡量采用 JSON 格式
  • 鑒權 - 采用 Autho2.0
    在此不再贅述

上一篇:Spring Cloud 零基礎實戰(zhàn)(五):訪問 MySQL 數(shù)據(jù)庫
下一篇:待續(xù)...
所屬文集:Spring Cloud 零基礎實戰(zhàn)


最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锅知,一起剝皮案震驚了整個濱河市播急,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌售睹,老刑警劉巖桩警,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異昌妹,居然都是意外死亡生真,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門捺宗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人川蒙,你說我怎么就攤上這事蚜厉。” “怎么了畜眨?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵昼牛,是天一觀的道長术瓮。 經(jīng)常有香客問我,道長贰健,這世上最難降的妖魔是什么胞四? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮伶椿,結果婚禮上辜伟,老公的妹妹穿的比我還像新娘。我一直安慰自己脊另,他們只是感情好导狡,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著偎痛,像睡著了一般旱捧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上踩麦,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天枚赡,我揣著相機與錄音,去河邊找鬼谓谦。 笑死贫橙,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的茁计。 我是一名探鬼主播料皇,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼星压!你這毒婦竟也來了践剂?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤娜膘,失蹤者是張志新(化名)和其女友劉穎逊脯,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竣贪,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡军洼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了演怎。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匕争。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖爷耀,靈堂內(nèi)的尸體忽然破棺而出甘桑,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布跑杭,位于F島的核電站铆帽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏德谅。R本人自食惡果不足惜爹橱,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窄做。 院中可真熱鬧愧驱,春花似錦、人聲如沸浸策。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庸汗。三九已至惫确,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蚯舱,已是汗流浹背改化。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留枉昏,地道東北人陈肛。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像兄裂,于是被迫代替她去往敵國和親句旱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360