搞懂什么是RESTful API?

基础概念

1. 什么是接口?

在软件开发中,接口就像是一个“桥梁”,它让不同的系统或程序能够互相通信。比如,你用手机上的天气应用,它需要从天气服务器获取数据,这个获取数据的过程就是通过接口完成的。

2. REST 是什么?

简单来说,REST 就是一套规则,告诉开发者怎么设计接口,让它们更简单、更高效、更通用。

3. RESTful 接口的特点

(1)无状态(Stateless)
  • 每次请求都是独立的,服务器不会保存上次请求的状态。
  • 比如,你打开一个网页,服务器不会记得你之前做过什么,每次请求都是新的。
(2)统一的接口(Uniform Interface)
  • 所有的操作都通过统一的方式进行,比如使用 HTTP 协议的几种方法(GET、POST、PUT、DELETE)。
(3)资源导向(Resource-Oriented)
  • 在 RESTful 接口中,一切都是“资源”,比如用户信息、文章、商品等。
  • 每个资源都有一个唯一的地址(URL),通过这个地址可以访问和操作资源。

4. HTTP 方法

RESTful 接口主要通过 HTTP 协议来实现,它使用几种常见的 HTTP 方法来操作资源:

(1)GET
  • 用来获取资源
  • 比如,你想从服务器上获取一篇文章的内容,就可以用 GET 方法。
(2)POST
  • 用来创建资源
  • 比如,你写了一篇新文章,想把它保存到服务器上,就可以用 POST 方法。
(3)PUT
  • 用来更新资源
  • 比如,你想修改一篇文章的内容,就可以用 PUT 方法。
(4)DELETE
  • 用来删除资源
  • 比如,你想删除一篇文章,就可以用 DELETE 方法。

5. 小例子

场景描述

假设我们正在开发一个图书馆管理系统,需要通过 RESTful 接口实现以下功能:

  1. 获取所有书籍的列表。
  2. 获取某一本特定书籍的详细信息。
  3. 添加一本新书。
  4. 更新某本书的信息。
  5. 删除某本书。
1. 定义资源

在 RESTful 接口中,一切都是“资源”。在这个例子中,书籍(Book) 就是一个资源。每本书可以用以下属性来描述:

  • id:书籍的唯一标识符(主键)。
  • title:书名。
  • author:作者。
  • isbn:国际标准书号。
  • published_date:出版日期。

2. 设计接口

根据 RESTful 的设计原则,我们需要为书籍资源定义统一的接口。以下是具体的设计:

(1)获取所有书籍
  • HTTP 方法GET
  • URL/api/books
  • 功能:返回图书馆中所有书籍的列表。
  • 返回数据
[
  {
    "id": 1,
    "title": "《百年孤独》",
    "author": "加西亚·马尔克斯",
    "isbn": "9787544274428",
    "published_date": "1967-05-01"
  },
  {
    "id": 2,
    "title": "《平凡的世界》",
    "author": "路遥",
    "isbn": "9787530212941",
    "published_date": "1986-12-01"
  }
]
(2)获取某一本特定书籍
  • HTTP 方法GET
  • URL/api/books/{id}{id} 是书籍的唯一标识符)
  • 功能:根据书籍的 id 返回该书的详细信息。
  • 示例请求GET /api/books/1
  • 返回数据
{
  "id": 1,
  "title": "《百年孤独》",
  "author": "加西亚·马尔克斯",
  "isbn": "9787544274428",
  "published_date": "1967-05-01"
}
(3)添加一本新书
  • HTTP 方法POST
  • URL/api/books
  • 功能:创建一本新书,并将其保存到数据库中。
  • 请求体
{
  "title": "《活着》",
  "author": "余华",
  "isbn": "9787530202922",
  "published_date": "1993-06-01"
}
  • 返回数据
{
  "id": 3,
  "title": "《活着》",
  "author": "余华",
  "isbn": "9787530202922",
  "published_date": "1993-06-01"
}
(4)更新某本书的信息
  • HTTP 方法PUT
  • URL/api/books/{id}{id} 是书籍的唯一标识符)
  • 功能:根据书籍的 id 更新该书的信息。
  • 示例请求PUT /api/books/1
  • 请求体
{
  "title": "《百年孤独》(修订版)",
  "author": "加西亚·马尔克斯",
  "isbn": "9787544274428",
  "published_date": "1967-05-01"
}
  • 返回数据
{
  "id": 1,
  "title": "《百年孤独》(修订版)",
  "author": "加西亚·马尔克斯",
  "isbn": "9787544274428",
  "published_date": "1967-05-01"
}
(5)删除某本书
  • HTTP 方法DELETE
  • URL/api/books/{id}{id} 是书籍的唯一标识符)
  • 功能:根据书籍的 id 删除该书。
  • 示例请求DELETE /api/books/2
  • 返回数据
{
  "message": "书籍删除成功",
  "deletedBookId": 2
}

3. 接口设计总结

通过以上设计,我们为图书馆的书籍资源定义了一组 RESTful 接口。这些接口遵循 REST 原则:

  • 使用统一的 HTTP 方法(GET、POST、PUT、DELETE)来操作资源。
  • 每个资源都有一个唯一的 URL(如 /api/books/{id})。
  • 接口简单、直观,易于理解和使用。
4. 实现示例(伪代码)

假设我们使用 Spring Boot 框架来实现这些接口,以下是伪代码示例:

@RestController
@RequestMapping("/api/books")
public class BookController {

    // 获取所有书籍
    @GetMapping
    public List<Book> getAllBooks() {
        // 从数据库获取所有书籍
        return bookService.findAll();
    }

    // 获取某本书
    @GetMapping("/{id}")
    public Book getBookById(@PathVariable Long id) {
        // 根据 ID 获取书籍
        return bookService.findById(id);
    }

    // 添加新书
    @PostMapping
    public Book addBook(@RequestBody Book book) {
        // 保存新书到数据库
        return bookService.save(book);
    }

    // 更新书籍
    @PutMapping("/{id}")
    public Book updateBook(@PathVariable Long id, @RequestBody Book book) {
        // 更新书籍信息
        return bookService.update(id, book);
    }

    // 删除书籍
    @DeleteMapping("/{id}")
    public void deleteBook(@PathVariable Long id) {
        // 删除书籍
        bookService.delete(id);
    }
}
@RequestParam@PathVariable 的对比

特性

@RequestParam

@PathVariable

用途

绑定查询参数或表单数据

绑定路径中的变量

请求类型

GET 请求的查询参数、POST 请求的表单数据

GET/POST 请求的路径变量

示例

/users?name=John&age=30

/users/123

默认值

支持默认值(defaultValue

不支持默认值

是否必须

可选(required = false

必须,路径变量通常不能省略

数据类型

任意类型(通过类型转换器转换)

任意类型(通过类型转换器转换)

总结

  • @RequestParam:用于处理查询参数,适用于分页、搜索、排序等场景。
  • @PathVariable:用于处理路径变量,适用于资源的 CRUD 操作。
  • 结合使用:在 RESTful API 中,@RequestParam@PathVariable 可以结合使用,以实现更灵活的资源访问和查询功能。
  • @RequestBody 的作用

@RequestBody 用于从请求的 正文(Body) 中读取数据,并将其绑定到方法的参数上,将数据自动反序列化为 Java 对象。它通常用于处理 POST 或 PUT 请求,这些请求通常携带 JSON 或 XML 格式的请求体。

总结

通过这个简单的例子,我们可以看到 RESTful 接口的设计步骤:

  1. 确定资源(如书籍)。
  2. 为资源定义统一的 URL 和 HTTP 方法。
  3. 根据需求实现具体的接口功能。

RESTfuI接口URL命名原则

RESTful 接口的 URL 命名需要遵循一定的原则,以确保接口的可读性、一致性和可维护性。以下是 RESTful 接口 URL 命名的最佳实践:

1. 使用小写字母
  • URL 应该使用小写字母,避免大小写混合。
  • 示例:/api/users 而不是 /api/Users
2. 使用名词而非动词
  • URL 应该表示资源,而不是操作。因此,应该使用名词而不是动词。
  • 错误示例:/getUser/deleteUser
  • 正确示例:/users/{id}
3. 使用复数形式
  • 对于集合资源,建议使用复数形式,以保持一致性,如:/users/{id}
4. 使用连字符(-)
  • 多单词的资源名称应使用连字符(-)分隔,避免使用下划线(_)或驼峰命名。
  • 错误示例:/user_profile/userProfile
  • 正确示例:/user-profile
5. 避免尾部斜杠
  • URL 不应以尾部斜杠结尾,以避免歧义。
  • 错误示例:/api/users/
  • 正确示例:/api/users
6. 资源嵌套层次
  • 资源嵌套应尽量简洁,避免过多层级,通常不超过两层。
  • 错误示例:/api/users/{id}/orders/{orderId}/items
  • 正确示例:/api/users/{id}/orders
7. 版本控制
  • 如果需要版本控制,可以在 URL 中包含版本号。
  • 示例:/v1/users
8. 清晰且有意义的路径
  • 资源名称应清晰且具有描述性,避免使用模糊的术语。
  • 错误示例:/items/{id}
  • 正确示例:/products/{productId}

复杂GET查询请求接口命名示例

在设计 RESTful 接口时,GET 请求通常用于获取资源,但有时我们需要进行复杂的查询,比如根据多个条件筛选资源。这种情况下,接口的命名和参数设计需要清晰、合理,以便于理解和使用。

1. 设计原则

在设计复杂查询的 GET 接口时,应遵循以下原则:

  1. 保持 URL 简洁:尽量避免过长的路径。
  2. 使用查询参数(Query Parameters):将复杂的查询条件作为查询参数传递,而不是放在路径中。
  3. 语义清晰:接口路径应清晰表达资源的类型,查询参数应具有明确的含义。
  4. 支持分页和排序:复杂查询通常需要支持分页和排序功能。
  5. 支持组合查询:允许客户端通过多个查询参数组合条件。

2. 示例:用户查询接口

假设我们有一个用户管理系统,需要支持以下查询功能:

  • 按用户名模糊查询。
  • 按邮箱精确查询。
  • 按年龄范围查询。
  • 按注册日期范围查询。
  • 支持分页和排序。
接口设计
GET /api/users
查询参数
  • username:用户名模糊匹配(支持通配符)。
  • email:邮箱精确匹配。
  • ageMinageMax:年龄范围。
  • registeredAfterregisteredBefore:注册日期范围。
  • pagesize:分页参数。
  • sort:排序字段(如 name,descemail,asc)。
示例请求
GET /api/users?username=Alice*&email=alice@example.com&ageMin=18&ageMax=30&registeredAfter=2020-01-01&registeredBefore=2023-12-31&page=1&size=10&sort=name,desc
返回数据示例
{
  "totalPages": 5,
  "totalElements": 45,
  "currentPage": 1,
  "pageSize": 10,
  "content": [
    {
      "id": 1,
      "username": "Alice",
      "email": "alice@example.com",
      "age": 25,
      "registeredDate": "2021-05-15"
    },
    {
      "id": 2,
      "username": "Alice123",
      "email": "alice123@example.com",
      "age": 22,
      "registeredDate": "2022-08-20"
    }
  ]
}

3. 示例:文章查询接口

假设我们有一个博客系统,需要支持以下查询功能:

  • 按标题模糊查询。
  • 按作者 ID 查询。
  • 按发布时间范围查询。
  • 按标签查询(支持多个标签)。
  • 支持分页和排序。
接口设计
GET /api/articles
查询参数
  • title:标题模糊匹配。
  • authorId:作者 ID。
  • publishedAfterpublishedBefore:发布时间范围。
  • tags:标签列表(支持多个标签,用逗号分隔)。
  • pagesize:分页参数。
  • sort:排序字段(如 publishedDate,descviews,asc)。
示例请求
GET /api/articles?title=Spring Boot*&authorId=123&publishedAfter=2023-01-01&publishedBefore=2024-01-01&tags=Java,Spring&page=0&size=20&sort=publishedDate,desc
返回数据示例
{
  "totalPages": 3,
  "totalElements": 50,
  "currentPage": 0,
  "pageSize": 20,
  "content": [
    {
      "id": 1,
      "title": "Spring Boot 教程",
      "authorId": 123,
      "publishedDate": "2023-05-10",
      "tags": ["Java", "Spring"]
    },
    {
      "id": 2,
      "title": "Spring Boot 最佳实践",
      "authorId": 123,
      "publishedDate": "2023-09-15",
      "tags": ["Java", "Spring"]
    }
  ]
}

RESTful 接口 URL 分级原则

RESTful 接口的 URL 分级结构设计是为了清晰表达资源之间的层次关系,同时保持简洁性和可维护性。以下是 RESTful 接口 URL 分级设计的最佳实践:

  1. 清晰的层级关系
    • /api/users:获取所有用户。
    • /api/users/{userId}:获取特定用户。
    • /api/users/{userId}/orders:获取特定用户的订单。
  1. 简洁的嵌套
    • /api/articles/{articleId}/comments:获取文章的所有评论。
  1. 版本控制
    • /api/v1/users:用户模块的 v1 版本。

HTTP 的幂等性

在 HTTP 协议中,幂等性(Idempotence) 是一个重要的概念,它描述的是某些 HTTP 方法在多次执行时的行为特性。简单来说,幂等性 指的是:多次执行相同的操作,结果是一样的,就好像执行了一次操作一样。

1. 幂等性的定义

如果一个 HTTP 方法是幂等的,那么无论你调用它一次还是多次,只要输入的参数相同,最终的结果(即对服务器状态的影响)是相同的。换句话说,多次调用不会产生额外的副作用。

2. HTTP 方法的幂等性

HTTP 协议定义了多种请求方法(如 GET、POST、PUT、DELETE 等),每种方法都有其特定的语义和幂等性特性:

(1)幂等的方法
  • GET
    • 语义:用于获取资源。
    • 幂等性:幂等。
    • 解释:无论调用多少次,GET 方法都不会对服务器状态产生任何改变,只是返回资源的内容。
  • PUT
    • 语义:用于更新或创建资源。
    • 幂等性:幂等。
    • 解释:多次调用 PUT 方法(假设请求体相同)会对资源产生相同的效果。例如,更新一个用户的邮箱地址,无论调用一次还是多次,结果都是相同的。
  • DELETE
    • 语义:用于删除资源。
    • 幂等性:幂等。
    • 解释:删除一个资源后,再次调用 DELETE 方法不会产生额外的影响。例如,删除一个文件后,再次删除该文件不会改变服务器的状态。
(2)非幂等的方法
  • POST
    • 语义:用于创建资源或触发服务器上的操作。
    • 幂等性:非幂等。
    • 解释:多次调用 POST 方法可能会产生不同的结果。例如,向数据库中插入一条新记录,每次调用都会创建一个新的记录,因此多次调用会产生不同的结果。

3. 幂等性的实际意义

幂等性在实际开发中非常重要,尤其是在分布式系统和网络不稳定的情况下。例如:

  • 网络重试:当客户端发送请求时,可能会因为网络问题导致请求失败。如果请求是幂等的,客户端可以安全地重试请求,而不用担心多次调用会产生意外的副作用。
  • 系统可靠性:幂等操作可以减少因重复请求导致的错误,提高系统的可靠性和可预测性。

4. 幂等性与安全性

幂等性与安全性(Safety)是两个不同的概念:

  • 幂等性(Idempotence):多次调用结果相同。
  • 安全性(Safety):不会对服务器状态产生副作用。
    • GET是安全的,因为它们不会修改服务器状态。
    • POSTPUTDELETE 是不安全的,因为它们会修改服务器状态。

5. 如何设计幂等的接口

在设计 RESTful 接口时,应尽量遵循 HTTP 方法的语义,并确保幂等性:

  • 使用 PUTDELETE 方法时,确保它们是幂等的。
  • 对于 POST 方法,如果需要幂等性,可以通过其他机制(如唯一标识符、幂等令牌)来避免重复操作。

6. 幂等性的例子

假设我们有一个用户管理系统,以下是幂等和非幂等操作的例子:

(1)幂等操作
  • 更新用户信息
PUT /api/users/123
{
  "name": "Alice",
  "email": "alice@example.com"
}
    • 解释:无论调用多少次,用户 123 的信息都会被更新为相同的值。
  • 删除用户
DELETE /api/users/123
    • 解释:删除用户 123 后,再次调用不会产生额外的影响。
(2)非幂等操作
  • 创建新用户
POST /api/users
{
  "name": "Bob",
  "email": "bob@example.com"
}
    • 解释:每次调用都会创建一个新的用户记录,因此多次调用会产生不同的结果。

7. 总结

幂等性是 HTTP 协议中的一个重要概念,它描述了某些操作在多次执行时的结果是否相同。幂等的操作(如 GETPUTDELETE)可以安全地重试,而不会产生意外的副作用。在设计 RESTful 接口时,应尽量遵循 HTTP 方法的语义,确保接口的幂等性和安全性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值