本文目录导读:

- 核心分层结构(基于 MVC + Service + DAO)
- 边界情况与规范处理
- 完整调用流程图示(规整版)
- 推荐依赖与版本(2024+ 常用)
- 高级规整要点(适合复杂项目)
- 总结:规整流程 = 统一对象 + 分层职责 + 参数校验 + 防止溢出 + VO转换
在Java开发中,规整分页调用流程的核心目标通常是:解耦、复用、清晰、避免内存溢出。
以下从架构分层、通用工具类、前端对接三个维度,给出一种业界常用的规整方案。
核心分层结构(基于 MVC + Service + DAO)
定义统一的分页请求与响应对象
通用请求对象(避免每个接口重复定义 pageNum, pageSize)
// PageRequest.java
@Data
public class PageRequest {
private int pageNum = 1;
private int pageSize = 10;
// 可选的排序字段
private String orderBy;
private boolean asc = true;
}
通用响应对象(封装总记录数、数据列表)
// PageResult.java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult<T> {
private long total; // 总记录数
private int pageNum; // 当前页码
private int pageSize; // 每页大小
private List<T> list; // 当前页数据
private int pages; // 总页数(可计算得出)
}
Controller 层:只负责参数校验和结果返回
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public ResponseEntity<PageResult<UserVO>> listUsers(PageRequest pageRequest,
@RequestParam(required = false) String name) {
// 1. 参数校验(可选,PageRequest可加@Valid)
// 2. 调用Service
PageResult<UserVO> result = userService.queryUsers(pageRequest, name);
return ResponseEntity.ok(result);
}
}
Service 层:核心业务逻辑 + 分页转换
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private UserConverter userConverter; // 使用 MapStruct 或手动转换
public PageResult<UserVO> queryUsers(PageRequest pageRequest, String name) {
// 方案一:使用 MyBatis-Plus 分页插件(推荐)
Page<User> page = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
if (StringUtils.isNotBlank(name)) {
wrapper.like(User::getName, name);
}
Page<User> userPage = userMapper.selectPage(page, wrapper);
// 将 PO 转换为 VO(脱敏、移除敏感字段)
List<UserVO> voList = userConverter.toVOList(userPage.getRecords());
return new PageResult<>(
userPage.getTotal(),
userPage.getCurrent(),
userPage.getSize(),
voList,
(int) userPage.getPages()
);
}
}
Mapper 层(DAO)
// 使用 MyBatis-Plus 时:只需继承 BaseMapper
public interface UserMapper extends BaseMapper<User> {
// 不需要额外写分页SQL,MyBatis-Plus 自动处理
}
如果使用 原生 MyBatis + PageHelper:
<select id="selectUsers" resultType="User">
SELECT * FROM user
<where>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
</where>
</select>
// Service中 PageHelper.startPage(pageRequest.getPageNum(), pageRequest.getPageSize()); List<User> users = userMapper.selectUsers(name); PageInfo<User> pageInfo = new PageInfo<>(users); // 转换为VO后构造PageResult
边界情况与规范处理
参数校验(防止异常页数)
// 在 Controller 或 全局过滤器中
public class PageValidator {
public static void validate(PageRequest pageRequest) {
if (pageRequest.getPageNum() < 1) {
pageRequest.setPageNum(1);
}
if (pageRequest.getPageSize() < 1) {
pageRequest.setPageSize(10);
}
// 防止大尺寸攻击或内存溢出
if (pageRequest.getPageSize() > 1000) {
pageRequest.setPageSize(1000);
}
}
}
优化建议(避免 count 性能问题)
- 如果明确只查一页数据且不需要知道总数(如移动端“加载更多”),可提供
NoCountPageRequest,SQL 中使用limit pageSize+1来判断是否有下一页。 - 大字段分页:如果列表不需要大文本字段(如
content),在 Mapper 中指定resultMap排除该字段。
前端期望的统一格式(建议遵守)
{
"code": 200,
"message": "success",
"data": {
"total": 100,
"pageNum": 1,
"pageSize": 10,
"pages": 10,
"list": [ ... ]
}
}
使用统一响应体包装 PageResult:
public class R<T> {
private int code;
private String message;
private T data;
}
完整调用流程图示(规整版)
客户端(前端)
│
▼
Controller(接收 PageRequest + 过滤条件)
│
├── 参数校验(pageNum, pageSize 范围限制)
│
▼
Service(业务逻辑层)
│
├── 1. 转换/构建查询条件(DTO → Entity)
├── 2. 调用 Mapper 分页查询(MyBatis-Plus Page / PageHelper)
├── 3. 从分页对象获取 total + records
├── 4. 将 PO 转为 VO(脱敏、格式化)
└── 5. 构造 PageResult<T> 返回
│
▼
Controller(将 PageResult 放入统一响应体 R 中)
│
▼
返回 JSON 给前端
推荐依赖与版本(2024+ 常用)
| 框架 | 推荐版本 | 分页方式 |
|---|---|---|
| Spring Boot 3.x / Spring 6 | 3+ | |
| MyBatis-Plus | 5.5+ | Page<T> 自动拦截 |
| PageHelper | x(适配 Spring Boot 3) | PageHelper.startPage() |
| MapStruct (DTO/VO转换) | 5+ | 自动生成转换代码 |
| Hibernate Validator | 6+ / 8+ | 参数校验 |
高级规整要点(适合复杂项目)
- 分页与过滤条件解耦:不要将
pageNum放在业务DTO中,单独使用PageRequest。 - 多表关联分页:如果使用 MyBatis-Plus
selectPage无法处理复杂JOIN,可以:- 先查主表ID列表进行分页
- 再
IN查关联数据 - 在内存中组装(注意数据量不能太大)
- 超大分页优化:使用覆盖索引 + 延迟关联(即先查ID,再JOIN主表)。
- 避免 N+1 问题:在循环中调用其他表的查询,应在分页前一次性查好。
规整流程 = 统一对象 + 分层职责 + 参数校验 + 防止溢出 + VO转换
如果需要代码模板(比如通用分页Service基类、自定义分页注解),可以进一步说明,我可以给出可复用的代码段。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播