第3章:列表与分页(List and Pagination)
一、导读
1.1 本章学习目标
第3章讲解列表操作和分页模式——处理大量数据的标准方式。
本章的核心学习目标包括:
- 掌握分页的两种模式:令牌分页和偏移分页
- 理解列表操作的过滤和排序
- 学会设计高效的列表 API
1.2 为什么本章如此重要
列表操作是最常见的 API 操作之一。分页设计不当会导致性能问题、数据不一致、用户体验差。
1.3 核心问题引导
令牌分页和偏移分页有什么区别?
为什么令牌分页更适合大数据集?
列表操作应该支持哪些过滤和排序选项?
如何设计高效的列表 API?
二、核心概念详解
2.1 令牌分页
// 请求
GET /api/v1/users?pageSize=20&pageToken=eyJpZCI6MTAwfQ
// 响应
{
"users": [...],
"nextPageToken": "eyJpZCI6MTIwfQ",
"totalSize": 1500 // 可选,可能不准确
}
// 优点:
// - 性能稳定(不受数据量影响)
// - 数据一致性好(不会跳过或重复)
// - 适合大数据集
// 缺点:
// - 不能跳页
// - Token 不透明2.2 偏移分页
// 请求
GET /api/v1/users?pageSize=20&pageNumber=3
// 响应
{
"users": [...],
"totalSize": 1500,
"pageNumber": 3,
"pageSize": 20,
"totalPages": 75
}
// 优点:
// - 可以跳页
// - 直观
// 缺点:
// - 性能随页码增加而下降
// - 数据一致性差(可能跳过或重复)2.3 过滤和排序
// 过滤
GET /api/v1/users?filter=status=ACTIVE&filter=role=admin
// 排序
GET /api/v1/users?orderBy=createdAt desc,name asc
// 组合
GET /api/v1/users?filter=status=ACTIVE&orderBy=createdAt desc&pageSize=20三、实战案例
3.1 案例一:令牌分页实现
java
public class UserListResponse {
private List<User> users;
private String nextPageToken;
public static UserListResponse from(
List<User> users, int pageSize
) {
String nextToken = null;
if (users.size() == pageSize) {
User last = users.get(users.size() - 1);
nextToken = encodeToken(last.getId());
}
return new UserListResponse(users, nextToken);
}
private static String encodeToken(String userId) {
return Base64.getUrlEncoder().encodeToString(
("id=" + userId).getBytes()
);
}
}四、本章小结
令牌分页:性能稳定,数据一致,适合大数据集。
偏移分页:可跳页,直观,但性能随页码下降。
过滤和排序:灵活的查询参数设计。
五、思考与练习
为一个订单列表 API 设计分页方案。
令牌分页和偏移分页各适用于什么场景?
如何设计支持复杂过滤条件的列表 API?