Java-020-RESTful

RESTful API

HTTP协议

  • URI – 互联网资源的地址
  • 操作 – 对资源执行的操作: GET, PUT, POST, DELETE
  • 返回状态码 – 表示执行结果: 200, 201, 403, 404, 500

以上是 HTTP协议在程序语义层面的定义, 同时也抽象了整个互联网内容的组织和交互方式.

  • 互联网上所有的内容都是资源, 每个资源有唯一的URI
  • 交互就是对互联网资源的操作(GET, PUT, POST, DELETE)
  • 然后资源的操作结果就是状态返回码

每一次请求的发起都是客户端向服务端发起.

RESTful API

RESTful API就是基于HTTP协议对互联网的内容定义的方式提出的一套互联网应用的架构体系.

RESTful是一种设计模式规范的指南, 不是一个强制性的要求, 所以遵守都必须是靠开发者自己遵守.

RESTful API的基本要求

URI

  1. 协议: HTTP或HTTPS
  2. 域名和地址一般格式: http://<域名>/api/

    1
    有 api 路径是为了版本的更新
  3. 域名和地址之后接资源名字统一用复数, 例如

    1
    2
    3
    https://api.example.com/v1/zoos
    https://api.example.com/v1/animals
    https://api.example.com/v1/employees

操作

  1. GET /accounts – 列出所有的账户信息
  2. GET /accounts/ – 查询id为的账户信息
  3. PUT /accounts/ – 更新id为的账户信息, 注意这个操作是幂等的, 幂等是多次同样的操作, 最终结果只有一个!
  4. POST /accounts – 创建一个新的账户
  5. DELETE /accounts – 删除一个账户 (危险操作)

额外参数

URI里的参数列表, 一般用在查询里面. 比如 GET /accounts?type=ADMIN 这样用来筛选账户, 一般不推荐直接把id这样直接资源的索引键值直接用在URL的参数列表里, 而是直接放在URI里, 因为它本身是一个资源!

状态转换

HTTP协议是无状态的, 也就是说, 客户端不保存状态, 然后通过RESTful API定义的操作改变资源在服务端的状态

返回状态

操作的执行结果

  • 请求负载和返回负载

JSON – JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。

JSON的基本结构是对象, 以及对象里的键值对, 例如:

1
2
3
4
{ "user": {
"username": "admin",
"password": "1234"}
};

详细资料参见: https://www.json.org/json-zh.html

或者XML

总结

我们如果反思一下上述对RESTful API的介绍, 是不是就很容易感觉到, 其实RESTful = HTTP + JSON

确实也是这样的

为什么我们需要RESTful API

  • 原生的互联网架构方式来建构互联网内容
  • 统一的通信协议和开发语义. 统一标准可以带来效率的提升和协作的高效
  • 接口一致, 操作没有歧义

RESTful API 扩展阅读

案例

登录逻辑

1
2
3
4
5
6
7
8
9
# 以前的登录url
/signup?username=abc&password=123456

POST /accounts

{
"username": "abc",
"password": "123456"
}

操作

1
2
3
4
5
6
7
8
9
GET /accounts 列举 -- ListAccounts(filter: AccountType, Account创建时间)
GET /accounts/<id> -- GetAccount()
PUT /accounts/<id> -- UpdateAccount()
POST /accounts -- CreateAccount()
DELETE /accounts -- DeleteAccount()

# 错误的url
GetAccount() -- GET /accounts?id= ->>>>>>>>>>>>>ListAccounts()
# url 应该用户一看到就知道是获取什么内容

状态码

  • 200, 201 – 成功
  • 400, 403, 404 – 用户的输入错误
  • 500 – 服务端的错误

我们RESTful API交互

  • 读别人的API, 然后理解和使用 => 用户
  • 写自己的API, 让别人理解和使用 => 开发者

读API

  1. 有什么资源, 资源的层次结构是什么样的?
    用户 -> 仓库 -> issues
  2. 操作: 增删改查
  3. 请求参数: URL的参数, 负载里的json
  4. 返回的状态(200, 201, 404) 和 返回的json格式

调用API

  1. 调用 API: 构造URL (资源) –> 发送响应请求(GET, POST, PUT) –> 参数
  2. 检验返回的状态码: 成功状态如何下一步的解析结果, 错误处理
  3. 解析结果

写RESTful API

  1. 想清楚我们的应用里可以抽象出什么样的资源, 和他们的层次结构
  2. 想清楚对对象的基本操作: GET, POST, PUT, DELETE的含义是什么
  3. 组织接口代码, Spring如何去定义这些路由(URI): URI -> Java类和方法
  4. 开始实现

Spring

资源

  • RestController
  • GetMapping, PutMapping, PostMapping, DeleteMapping: URI -> Java类和方法

参数

  • RequestParam: URL额外参数
  • PathVariable
  • RequestBody

处理逻辑*

  • 遵循Java代码的组织和开发方式
  • 面向对象的方式抽象和组织代码

状态和结果

  • 使用正确和准确的状态码!
  • 返回结果!
  • ResponseEntity
  • HttpStatus

PUT和POST的比较

  • PUT – 做具体资源的更新
  • POST – 创建新的资源, 在资源列表里添加一个资源

PUT — PUT操作是幂等的! op^n == op^(n + 1), 所以用PUT来做整体更新的时候, 多次重复同样内容的更新操作, 最终产生的结果是一致的!

所以在代码实现PUT操作时候, 要把这个操作实现成幂等的!

POST — POST操作不是幂等的! 创建的操作