The World Best ST.

Restful接口

字数统计: 1.7k阅读时长: 7 min
2019/04/13 Share

Restful

老是在各种文档里和博客里看到Restful还有Restful Api,那么Restful到底是什么呢?

REST的中文名是表述性状态转移,指的是一组架构约束条件和原则。如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。

REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力, 更好地使用现有Web标准中的一些准则和约束。虽然REST本身受Web技术的影响很深, 但是理论上REST架构风格并不是绑定在HTTP上,只不过目前HTTP是唯一与REST相关的实例。

URL的设计技巧

  • 使用_或者-来使URL的可读性更好
  • 使用/来表示资源的层级关系
    例如:/orders/2012/10可以用来表示2012年10月的订单记录

  • 使用?来过滤资源
    例如:/pulls?state=closed用来表示已经关闭的推入请求
    ?limit=10:指定返回记录的数量
    ?offset=10:指定返回记录的开始位置
    ?page=2&per_page=100:指定第几页,以及每页的记录数
    ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
    ?animal_type_id=1:指定筛选条件

  • ,或者;可以用来表示同级资源的关系
    例如:/git/block-sha1/sha1.h/compare/aaaa;bbbb来表示某个文件在随意两次提交记录之间的差异

  • 可以做到版本控制
    例如:/v1/users/{username}

几种请求方式

GET,HEAD,DELETE,PUT,POST,PATCH

安全性:对该REST接口访问,不会使服务器端资源的状态发生改变
幂等性:对同一REST接口多次访问,得到的资源状态是相同的
GET和HEAD请求都是安全的, 无论请求多少次,都不会改变服务器状态。而GET、HEAD、PUT和DELETE请求都是幂等的,无论对资源操作多少次, 结果总是一样的,后面的请求并不会产生比第一次更多的影响

GET

  • 安全且幂等
  • 获取表示
  • 变更时获取表示(缓存)
  • 200(OK) 表示已在响应中发出
  • 204(无内容) 资源有空表示
  • 301(Moved Permanently) 资源的URI已被更新
  • 303(See Other) 其他(如,负载均衡)
  • 304(not modified)资源未更改(缓存)
  • 400 (bad request)指代坏请求(如,参数错误)
  • 404 (not found)资源不存在
  • 406 (not acceptable)服务端不支持所需表示
  • 500 (internal server error)通用错误响应
  • 503 (Service Unavailable)服务端当前无法处理请求

栗子:

获取单一资源
GET /goods/1
获取资源集合
GET /goods/1/pictures

POST

  • 不安全且不幂等
  • 使用服务端管理的(自动产生)的实例号创建资源
  • 创建子资源
  • 部分更新资源
  • 如果没有被修改,则不过更新资源(乐观锁)
  • 200(OK)如果现有资源已被更改
  • 201(created)如果新资源被创建
  • 202(accepted)已接受处理请求但尚未完成(异步处理)
  • 301(Moved Permanently)资源的URI被更新
  • 303(See Other)其他(如,负载均衡)
  • 400(bad request)指代坏请求
  • 404 (not found)资源不存在
  • 406 (not acceptable)服务端不支持所需表示
  • 409 (conflict)通用冲突
  • 412 (Precondition Failed)前置条件失败(如执行条件更新时的冲突)
  • 415 (unsupported media type)接受到的表示不受支持
  • 500 (internal server error)通用错误响应
  • 503 (Service Unavailable)服务当前无法处理请求

PUT

  • 不安全但幂等
  • 用客户端管理的实例号创建一个资源
  • 通过替换的方式更新资源
  • 如果未被修改,则更新资源(乐观锁)
  • 200 (OK)如果已存在资源被更改
  • 201 (created)如果新资源被创建
  • 301(Moved Permanently)资源的URI已更改
  • 303 (See Other)其他(如,负载均衡)
  • 400 (bad request)指代坏请求
  • 404 (not found)资源不存在
  • 406 (not acceptable)服务端不支持所需表示
  • 409 (conflict)通用冲突
  • 412 (Precondition Failed)前置条件失败(如执行条件更新时的冲突)
  • 415 (unsupported media type)接受到的表示不受支持
  • 500 (internal server error)通用错误响应
  • 503 (Service Unavailable)服务当前无法处理请求

DELETE

  • 不安全但幂等
  • 删除资源
  • 200 (OK)资源已被删除
  • 301 (Moved Permanently)资源的URI已更改
  • 303 (See Other)其他,如负载均衡
  • 400 (bad request)指代坏请求
  • 404 (not found)资源不存在
  • 409 (conflict)通用冲突
  • 500 (internal server error)通用错误响应
  • 503 (Service Unavailable)服务端当前无法处理请求

常见问题及注意事项

  • POST和PUT有什么不同?
    POST相当于新建一个资源,PUT相当于更新资源

  • 在RESTful中应该只表示自愿的名称,而不应该包括资源的操作,如:
    Get /getUser/1
    POST /createUser
    PUT /updateUser/1
    DELETE /deleteUser/1

  • Hypermedia API ,RESTful API 最好做到Hypermedia,即返回结果中提供链接-连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

    1
    2
    3
    4
    5
    6
    {"link": {
    "rel": "collection https://www.example.com/zoos",
    "href": "https://api.example.com/zoos",
    "title": "List of zoos",
    "type": "application/vnd.yourformat+json"
    }}

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package cn.itcast.mybatis.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.itcast.mybatis.pojo.User;
import cn.itcast.mybatis.service.NewUserService;

@RequestMapping("restful/user")
@Controller
public class RestUserController {

@Autowired
private NewUserService newUserService;

/**
* 根据用户id查询用户数据
*
* @param id
* @return
*/
@RequestMapping(value = "{id}", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<User> queryUserById(@PathVariable("id") Long id) {
try {
User user = this.newUserService.queryUserById(id);
if (null == user) {
// 资源不存在,响应404
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
// 200
// return ResponseEntity.status(HttpStatus.OK).body(user);
return ResponseEntity.ok(user);
} catch (Exception e) {
e.printStackTrace();
}
// 500
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}

/**
* 新增用户
*
* @param user
* @return
*/
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<Void> saveUser(User user) {
try {
this.newUserService.saveUser(user);
return ResponseEntity.status(HttpStatus.CREATED).build();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 500
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}

/**
* 更新用户资源
*
* @param user
* @return
*/
@RequestMapping(method = RequestMethod.PUT)
public ResponseEntity<Void> updateUser(User user) {
try {
this.newUserService.updateUser(user);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
} catch (Exception e) {
e.printStackTrace();
}
// 500
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}

/**
* 删除用户资源
*
* @param user
* @return
*/
@RequestMapping(method = RequestMethod.DELETE)
public ResponseEntity<Void> deleteUser(@RequestParam(value = "id", defaultValue = "0") Long id) {
try {
if (id.intValue() == 0) {
// 请求参数有误
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
this.newUserService.deleteUserById(id);
// 204
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
} catch (Exception e) {
e.printStackTrace();
}
// 500
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}
}

参考资料:
https://www.runoob.com/w3cnote/restful-architecture.html
https://blog.csdn.net/chenxiaochan/article/details/73716617
https://blog.csdn.net/hzy38324/article/details/78360525?utm_source=gold_browser_extension

CATALOG
  1. 1. Restful
    1. 1.0.0.1. URL的设计技巧
  • 1.1. 几种请求方式
    1. 1.1.1. GET
    2. 1.1.2. POST
    3. 1.1.3. PUT
    4. 1.1.4. DELETE
  • 1.2. 常见问题及注意事项
  • 1.3. 代码实现