jcalaBlog 分页功能实现原理:MyBatis 手动分页的完整思路
2026/8/21 13:59:20 网站建设 项目流程

jcalaBlog 分页功能实现原理:MyBatis 手动分页的完整思路

【免费下载链接】jcalaBloga personal blog site based on springboot+srpingMVC+mybatis+velocity+bootstrap+mysql项目地址: https://gitcode.com/gh_mirrors/jc/jcalaBlog

jcalaBlog 是一个基于 Spring Boot + Spring MVC + MyBatis + MySQL 构建的个人博客项目,它的分页功能没有依赖 PageHelper 等插件,而是采用MyBatis 手动分页。本文将从源码入手逐层拆解 jcalaBlog 分页功能实现原理,带你理解「页码 → 偏移量 → LIMIT 语句 → 页面渲染」的完整链路,这套思路同样适用于任何使用 MySQL 的后端项目。

为什么选择 MyBatis 手动分页?🤔

很多新手一提到分页,第一反应就是引入 PageHelper 插件。而 jcalaBlog 选择了最朴素、也最能看清本质的方式——MyBatis 手动分页,即在 SQL 中直接书写LIMIT关键字完成数据切片。它的核心公式只有一句话:

起始偏移量 start = (当前页码 - 1) × 每页条数

手动分页的好处非常明显:SQL 完全可控、依赖极少、原理透明,非常适合个人博客这种数据量不大的场景。下面我们就沿着 Controller → Service → Mapper 的调用顺序,一步步看清它是怎么落地的。

后台博客列表:分页的典型示范 📄

先看效果。jcalaBlog 后台的「Blog List」页面就是一个标准的分页列表,表格下方带有页码控件和上/下页箭头,这正是我们要拆解的目标:

可以看到,分页并不神秘:前端只负责展示「第几页」,后端负责算出「该取哪些数据」。接下来进入源码环节。

第一步:Mapper 层用 LIMIT 完成手动分页 SQL

jcalaBlog 的分页 SQL 全部写在 Mapper 接口的注解里,核心方法在 BlogMapper.java:

@Select({ "select vid,title,tags", "from blog_view", "limit #{st},10" }) List<BlogView> selectTenBlogs(@Param("st") int start);

这里就是MyBatis 手动分页的关键:limit #{st},10表示跳过前st条、再取 10 条。MySQL 中LIMIT 偏移量, 条数的语义,让 Mapper 只需要接收一个「偏移量」参数即可,配合select count(*)统计总数,分页所需的两块拼图就齐了。

类似的写法还出现在归档页 BlogMapper.java(每页 12 条)和项目列表 ProjectMapper.java(每页 5 条)中,说明这套模式在项目里被广泛复用。

第二步:Service 层把页码换算成偏移量

Mapper 只认「偏移量」,不认「页码」,中间的换算由 Service 层完成。见 BlogSerImpl.java:

public List<BlogView> getBlogPage(int id){ int start = (id - 1) * 10; return blogMapper.selectTenBlogs(start); }

这就是手动分页最精华的一行:(id - 1) * 10。把页码与每页条数(10)相乘,就得到要跳过的记录数。页码与偏移量的换算关系如下:

页码偏移量 (pageSize=10)取出的记录
10第 1~10 条
210第 11~20 条
320第 21~30 条

归档页的getArchive(int page)同理,只是每页条数换成了 12:BlogSerImpl.java。

第三步:总页数计算,决定分页条渲染几个数字

光有当前页数据还不够,页面底部还要显示「一共有几页」。jcalaBlog 的做法是先count总数,再向上取整,见 BlogSerImpl.java:

int num = blogMapper.selectBlogNum(); return num % 10 == 0 ? num / 10 : num / 10 + 1;

逻辑很好懂:总数能被 10 整除就整除,否则加一页。比如 23 篇文章、每页 10 条,就会得到 3 页。由于归档页每页 12 条,getArchiveNum()也按同样的思路独立计算了一次。

第四步:Controller 通过路径变量接收页码

页码怎么从 URL 进到代码里?答案是 Spring MVC 的@PathVariable。后台列表见 BlogCtrl.java:

@GetMapping("/blogList/{page}") public String blogList(@PathVariable int page, Model model) { model.addAttribute("current", page); model.addAttribute("pageNum", blogSer.adminGetPageNum()); model.addAttribute("blogList", blogSer.getBlogPage(page)); return "admin/blog_list"; }

前端归档页也完全一致,通过/archives/{page}接收页码并注入模型:FontEndCtrl.java。这样一次请求就拿到了三样东西:当前页数据、总页数、当前页码,接下来就交给模板渲染。

第五步:Velocity 分页宏统一渲染翻页控件

jcalaBlog 使用 Velocity 模板引擎,翻页控件被封装成了可复用的宏#flip,定义在 VM_global_library.vm。它接收三个参数——总页数、当前页、链接前缀,内部用$current - 1$current + 1生成上一页/下一页地址,并用循环输出所有页码:

  • 后台列表页调用:#flip($pageNum $current $href),见 blog_list.vm
  • 前端归档页调用:#frontFlip($pageNum $current $href)(只有上一页/下一页两种按钮),见 archives.vm

宏的复用让所有分页页面保持了一致的视觉风格,改一处即可全局生效。

完整流程串起来:一次点击发生了什么?🔗

把上面的环节连起来,一次翻页操作的完整链路是:

  1. 用户点击「第 2 页」,浏览器请求/admin/blogList/2
  2. Controller 用@PathVariable拿到页码2,同时查出总页数;
  3. Service 计算偏移量(2-1)*10 = 10,调用 Mapper;
  4. Mapper 执行select ... limit 10,10,从第 11 条开始取 10 条;
  5. 数据、总页数、当前页码一起放进 Model;
  6. Velocity 模板渲染列表与分页宏,用户在浏览器看到第 2 页内容。

整个过程没有一行插件代码,全靠 MyBatis 手动分页的LIMIT与页码换算,条理清晰、极易排查问题。

写在最后:这套分页思路能给你什么启发?💡

通过 jcalaBlog 分页功能实现原理,你至少收获了三件事:一是记住了MyBatis 手动分页的核心公式start = (page-1) * size;二是学会了用「Controller 收页码 → Service 算偏移 → Mapper 执行 LIMIT → 模板渲染」的四层协作模式组织代码;三是理解了count总数与向上取整的总页数计算技巧。下次遇到分页需求,不妨先用手动方式把原理吃透,再决定是否引入插件——毕竟,知其然更要知其所以然。

如果觉得文章有帮助,欢迎收藏转发,让更多初学者看懂分页这件事!🚀

【免费下载链接】jcalaBloga personal blog site based on springboot+srpingMVC+mybatis+velocity+bootstrap+mysql项目地址: https://gitcode.com/gh_mirrors/jc/jcalaBlog

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询