一:RESTful是什么
- 1:RESTful是一種架構(gòu)風(fēng)格距辆,是一種描述語言喷兼,不是一個(gè)標(biāo)準(zhǔn)
- 2:RESTful核心就是rest绍赛,rest是幾個(gè)單詞的縮寫(REpresentational State Transfer)趾痘,各種國人寫的文檔都是直譯為:表現(xiàn)層狀態(tài)轉(zhuǎn)移逆济。這對一些剛接觸的人來說都是一臉懵蜀肘,和我們剛接觸Spring的IOC(控制反轉(zhuǎn))一樣绊汹,理解了好長時(shí)間才明白其中意思。很多軟件的一些專業(yè)詞匯都缺乏主語和賓語扮宠,增加了理解的難度西乖。rest的主語就是各種Resource(文檔,音樂坛增,視頻)获雕。具體真正完整的描述應(yīng)該是:資源在網(wǎng)絡(luò)請求中以某種的表現(xiàn)形式把狀態(tài)進(jìn)行了改變
- 3:資源在網(wǎng)絡(luò)上有特定的實(shí)體,互聯(lián)網(wǎng)有一個(gè)統(tǒng)一資源定位符(URI)來指向它
- 4:REST使用的是HTTP,URI,XML等已有的協(xié)議和標(biāo)準(zhǔn)
二:為什么要使用RESTful架構(gòu)風(fēng)格的接口
- 統(tǒng)一請求風(fēng)格收捣,用于各種前端的訪問
- Restful的API是面向資源的届案,非常清晰,根據(jù)url就知道內(nèi)容
- 輕量罢艾,直接基于http
三:設(shè)計(jì)RESTful接口的規(guī)范
概念 |
含義 |
冪等性 |
一個(gè)操作或者多個(gè)操作導(dǎo)致資源的結(jié)果是一樣的 |
RFC |
Internet服務(wù)的標(biāo)準(zhǔn),通常標(biāo)準(zhǔn)文件由數(shù)字標(biāo)識昆婿,數(shù)字越大球碉,代表標(biāo)準(zhǔn)越新 |
URI |
表示資源,資源對應(yīng)的是服務(wù)器端領(lǐng)域模型的實(shí)體類 |
Endpoint |
路徑仓蛆,表示api的具體網(wǎng)址 |
- 我們在設(shè)計(jì)符合restful規(guī)則API時(shí)候要知道我們一個(gè)api是對資源的操作睁冬,這是個(gè)前提。所以我們重要考慮的點(diǎn)在URI的Endpoint,請求方式豆拨,入?yún)?/strong>直奋,返回結(jié)果和異常這幾個(gè)方面來考慮
1:URI規(guī)范
@GetMapping("/api/app/Order") //Order大寫字母開頭,錯(cuò)誤
@GetMapping("/api/app/orders") //正確
@GetMapping("/api/app/order") //order不是復(fù)數(shù)施禾,錯(cuò)誤
@GetMapping("/api/app/orders") //正確
@GetMapping("/api/app/order_type/1") //錯(cuò)誤
@GetMapping("/api/app/order-type/1") //正確
- (4)避免層級過深的URI,過深導(dǎo)航會導(dǎo)致URI膨脹脚线,不易維護(hù)
@GetMapping("/api/app/orders/1/good-type/1") //錯(cuò)誤
@RequestMapping("/api/app/orders"){
@RequestParam(value = "goodType") Integer goodsType} //正確
2:Request規(guī)范
- HTTP有五種方法對URI進(jìn)行CURD操作,每個(gè)的冪等性都不一樣弥搞,可以按照下面規(guī)范定義不同的操作
方法 |
含義 |
冪等性 |
DEMO |
GET |
查詢 |
是 |
/api/orders |
POST |
新增 |
否 |
/api/orders |
PUT |
修改完整資源 |
是 |
/api/orders/1 |
PATCH |
修改部分屬性 |
否 |
/api/orders/1 |
DELETE |
刪除資源 |
是 |
/api/orders/1 |
3:response規(guī)范
- (1)只返回?cái)?shù)據(jù)退唠,不包裝,我們的一個(gè)具體的測試工程項(xiàng)目返回的接口牛隅,只有返回?cái)?shù)據(jù)
{
"id": "1246021398806081538",
"projectName": "沈磊的項(xiàng)目",
"companyId": "1246020467318276097",
"companyName": "沈磊的企業(yè)",
"address": "北京第二小學(xué)",
"type": 3,
"firstPartName": "我不太清楚甲方是誰",
"secondPartName": null,
"contractAmount": 222558,
"deviceCategory": 5,
"deviceBrand": "北京",
"deviceAmount": 333586,
"upstreamSupplierType": 3,
"upstreamSupplierName": "上游供應(yīng)商的東西",
"createBy": "艾新建",
"updateTime": "2020-04-03 18:27:20",
"updateBy": "艾新建"
}
- (2)各HTTP方法成功處理后的數(shù)據(jù)格式
方法 |
返回格式 |
GET |
查詢的對象 |
POST |
新增成功的對象 |
PUT |
更新成功的對象 |
PATCH |
更新成功的對象 |
DELETE |
空 |
4:錯(cuò)誤碼規(guī)范
- 業(yè)務(wù)類異常controller層做統(tǒng)一攔截嗜浮,統(tǒng)一錯(cuò)誤碼500
- 使用http自帶的狀態(tài)碼皿曲,不許自定義
5:完整的demo
根據(jù)我們已有的項(xiàng)目,包含完整的CURD的操作粤铭,展示出來供參考
@ApiOperation(value = "查詢工程項(xiàng)目詳情",notes = "查詢工程項(xiàng)目詳情",httpMethod = "GET")
@GetMapping("/{id}")
public Project detail(@PathVariable("id") Long id) {
return projectService.detail(id);
}
@ApiOperation(value = "添加工程項(xiàng)目",notes = "添加工程項(xiàng)目",httpMethod = "POST")
@PostMapping
public Project add(@RequestBody@Valid ReqProject req) {
return projectService.add(req);
}
@ApiOperation(value = "修改項(xiàng)目工程", notes = "修改工程項(xiàng)目", httpMethod = "PUT")
@PutMapping
public Project update(@RequestBody @Valid ReqProject req) {
return projectService.update(req);
}
@ApiOperation(value = "查詢工程項(xiàng)目列表(分頁)",notes = "查詢工程項(xiàng)目列表(分頁)",httpMethod = "GET")
@GetMapping(value = "/page")
public IPage<RespProject> page(ReqProjectQuery req) {
return projectService.page(req);
}
@ApiOperation(value = "刪除工程項(xiàng)目",notes = "刪除工程項(xiàng)目",httpMethod = "DELETE")
@DeleteMapping("/{id}")
public void delete(@PathVariable("id") Long id) {
log.info("查詢工程信息詳情入?yún)ⅲ簕}",id);
projectService.delete(id);
}