跳到主要内容 全栈分页方案:MyBatisPlus 与 Thymeleaf 整合实现 | 极客日志
Java 大前端 java
全栈分页方案:MyBatisPlus 与 Thymeleaf 整合实现 基于 MyBatisPlus 和 Thymeleaf 的全栈分页解决方案。涵盖环境搭建、实体类定义、业务层分页逻辑、控制层 API 交互及前端表格与分页条集成。通过配置分页插件解决分页不展示问题,实现后端数据查询与前端渲染对接,提升系统性能与用户体验。
星星泡饭 发布于 2026/2/8 更新于 2026/4/18 5.4K 浏览前言
分页功能是现代应用开发中不可或缺的一部分。通过 MyBatisPlus 和 Thymeleaf 的深度整合,可以实现一个高效、稳定的全栈分页解决方案。本文将介绍如何通过 MyBatisPlus 和 Thymeleaf 的整合,打造一个完整的全栈分页方案。
一、MybatisPlus 搭建及表介绍
MyBatisPlus 是一款基于 MyBatis 的增强版 ORM 框架,它不仅继承了 MyBatis 的灵活性和易用性,还提供了诸如分页插件、代码生成器等强大的功能,极大地简化了开发流程。通过 MyBatisPlus 的分页插件,开发者可以轻松实现高效的分页查询,而无需手动编写复杂的 SQL 分页逻辑。
1、MybatisPlus 环境搭建
这里以 Maven 为例,在 Pom.xml 文件通过增加以下依赖来引入 MybatisPlus,这里我们需要集成 PostgreSQL 数据库,因此还需要同时引入对应的数据库驱动包,在 JavaBean 的生成过程中,为了简化 Get 和 Set 等方法,还需要引入 Lombok 组件,对应的资源引入 xml 文件如下:
<dependency >
<groupId > com.baomidou</groupId >
<artifactId > mybatis-plus-boot-starter</artifactId >
<version > ${mybatis-plus.version}</version >
</dependency >
<dependency >
<groupId > org.projectlombok</groupId >
<artifactId > lombok</artifactId >
<scope > provided</scope >
</dependency >
<dependency >
<groupId > net.postgis</groupId >
<artifactId > postgis-jdbc
2.5.0
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
</artifactId >
<version >
</version >
</dependency >
2、示例表结构介绍 这里使用城市停水信息数据为例,重点介绍如何进行数据的分页展示,在正式介绍分页实现之前,首先将基础的表结构和示例数据给大家做一个介绍。其表结构如下:
二、Java 后台分页实现 本节将使用 Java 开发语言,结合 MybatisPlus 框架详细介绍在后台如何实现前端的分页需求。包含三个方面的内容,第一个方面是介绍业务实体的实现,第二个方面是介绍业务层如何进行分页实现,第三方面是控制层的 API 如何跟前端交互。
1、实体类实现 实体的实现比较简单,这里直接给出具体的 Java 代码如下:
package org.yelang.pcwater.domain;
import java.io.Serializable;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@TableName(value = "biz_stop_water_info")
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@ToString
public class StopWaterInfo implements Serializable {
private static final long serialVersionUID = -1582687729349525826L ;
@TableId(value="pk_id")
private Long pkId;
@TableField(value = "affect_user")
private String affectUser;
@TableField(value = "affected_range")
private String affectedRange;
@TableField(value = "affect_region")
private String affectRegion;
@TableField(value = "created_on")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createdOn;
@TableField(value = "inform_emergency_plan")
private String informEmergencyPlan;
@TableField(value = "inform_id")
private Integer informId;
@TableField(value = "inform_remark")
private String informRemark;
@TableField(value = "main_lead_path")
private String mainLeadPath;
private String position;
private String reason;
@TableField(value = "service_phone")
private String servicePhone;
@TableField(value = "show_end_date")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@SerializedName("showenddate")
private Date showEndDate;
@TableField(value = "stop_end_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date stopEndTime;
@TableField(value = "stop_start_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date stopStartTime;
@TableField(value = "stop_time")
@SerializedName("stoptime")
private String stopTime;
@TableField(value = "stopwater_type")
private String stopwaterType;
@TableField(value = "supply_emergency_plan")
private String supplyEmergencyPlan;
@TableField(value = "supply_remark")
private String supplyRemark;
private String title;
private String type;
@TableField(value = "regin_name")
private String reginName;
@TableField(value = "sync_sno")
private Long syncSno;
}
2、业务层分页实现 在查询业务中,分页是一个重要的核心,这里我们将具体的实现逻辑都放到业务层来实现,在这里需要使用一个非常重要的对象 Page 分页对象,这是 MybatisPlus 的一个基础分页组件,这里也是使用这个对象来完成具体的业务。首先我们在业务接口中定义如下方法:
IPage<StopWaterInfo> page (Integer pageNum, Integer pageSize,String regionName) ;
@Override
public IPage<StopWaterInfo> page (Integer pageNum, Integer pageSize, String regionName) {
QueryWrapper<StopWaterInfo> queryWrapper = new QueryWrapper <StopWaterInfo>();
queryWrapper.like("regin_name" , regionName);
queryWrapper.orderByDesc("created_on" );
Page<StopWaterInfo> page = new Page <StopWaterInfo>(pageNum, pageSize);
return this .baseMapper.selectPage(page, queryWrapper);
}
这里我们通过构造 Page 对象,将控制层传入的当前页面和每页显示的数据量大小一起传入,然后构造分页信息,一起传给 MybatisPlus 来进行查询方法的实现。
3、控制层实现 控制层比较简单,接收前端提交的三个参数,当前页数,每页显示数据量,还有一个查询条件参数。然后调用业务层的分页方法,最后将结果回写给前端,核心代码如下:
@PostMapping("/list")
@ResponseBody
public AjaxResult list (@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "5") Integer pageSize,
@RequestParam(defaultValue = "") String regionName) {
IPage<StopWaterInfo> page = waterInfoService.page(pageNum, pageSize, regionName);
AjaxResult result = AjaxResult.success();
result.put("data" , page);
return result;
}
三、Thymeleaf 分页集成 Thymeleaf 是一种现代的 Java 模板引擎,它能够很好地与 Spring Boot 集成,提供了一种优雅的方式来构建动态 HTML 页面。Thymeleaf 的优势在于它能够在开发阶段以静态 HTML 的形式展示页面,这使得前端开发变得更加直观和便捷。同时,Thymeleaf 提供了丰富的表达式和标签,能够方便地实现数据绑定和页面渲染。本节将具体介绍如何在 Thymeleaf 中集成后端的分页应用,并且实现分页条。
1、分页表格展示 为了在表格中展示相关的数据,我们首先需要在 Html 中定义以下 html 结构:
<div >
<table >
<thead >
<tr >
<th > 创建时间</th >
<th > 停水地点</th >
<th > 原因</th >
</tr >
</thead >
<tbody >
<tr th:if ="${#lists.isEmpty(waterEvents)}" >
<td colspan ="3" > 请点击查询按钮加载数据。</td >
</tr >
</tbody >
</table >
</div >
为了演示简单,这里使用 ajax 的方式从后天加载相应的数据,示例代码如下:
function renderTablePage (page ) {
currentPage = page;
const tableBody = document .getElementById ('table-body' );
tableBody.innerHTML = '' ;
$.ajax ({
type :"post" ,
url :ctx + "datasync/list" ,
dataType :"json" ,
cache :false ,
processData :true ,
data : {"pageNum" :page,"pageSize" :EVENTS_PER_PAGE ,"regionName" :"" },
success :function (result ){
const pageData = result.data .records ;
const totalPages = result.data .pages ;
if (pageData.length === 0 ) {
tableBody.innerHTML = `<tr><td colspan="5">未找到符合条件的停水事件。</td></tr>` ;
} else {
pageData.forEach (event => {
const row = tableBody.insertRow ();
row.innerHTML = `
<td>${event.createdOn} </td>
<td>${event.position} </td>
<td>${event.reason} </td>
` ;
});
}
renderPagination (totalPages);
},
error :function ( ){
tableBody.innerHTML = `<tr><td colspan="5">未找到符合条件的停水事件。</td></tr>` ;
}
});
}
通过代码可以看到,在拿到后台的响应数据后,我们将循环数据来动态实现表格数据的拼接展示。同时将生成分页条。
2、分页条集成 分页条的展示也需要在网页中插入页面元素,在 html 页面中定义以下网页标签,如下:
<div >
<nav aria-label ="Table Pagination" >
<ul > </ul >
</nav >
</div >
在获取表格数据的同时,我们就可以来同步设置分页条的,分页条的这里不采用特别复杂的样式,仅展示上一页和下一页,对应的代码如下:
function renderPagination (totalPages ) {
const paginationContainer = document .getElementById ('table-pagination' );
paginationContainer.innerHTML = '' ;
if (totalPages <= 1 ) return ;
paginationContainer.innerHTML += `
<li ${currentPage > 1 ? '' : 'disabled' } >
<a href="#" onclick="changePage(${totalPages} ,${currentPage - 1 } )" aria-label="Previous">前一页</a>
</li>
` ;
paginationContainer.innerHTML += `
<li ${currentPage >= totalPages ? 'disabled' : '' } >
<a href="#" onclick="changePage(${totalPages} ,${currentPage + 1 } )" aria-label="Next">后一页</a>
</li>
` ;
}
3、成果展示
四、可能遇到的问题 本节将介绍一个在实现分页应用的过程中经常容易遇到的问题,也就是没有得到分页信息的问题。以及如何来解决。
1、分页不展示 在成果页面中可以看到,正常的页面是每页展示若干条,而且表格下方带了分页条的。如果你也能实现,说明配置没有问题。如果你的应用截图如下:
出现了数据全部加载的问题。那么可以看看本节的解决方案。
2、问题解决 如果你也遇到这种没有分页条的情况,大概率是遇到了没有正确设置 Mybatis 的数据库分页插件的问题。导致了业务层在执行业务中,没有正确处理分页问题。解决的办法也很简单,在后台配置好分页插件即可。配置方法如下:
package org.yelang.pcwater.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor () {
MybatisPlusInterceptor i = new MybatisPlusInterceptor ();
i.addInnerInterceptor(new PaginationInnerInterceptor (DbType.POSTGRE_SQL));
return i;
}
}
配置好以上代码后,再次运行程序,你就会发现已经成功的出现了分页条。
五、总结 以上就是本文的主要内容,本文的目标是为开发者提供一个完整的全栈分页解决方案,从基础概念到具体实现,再到实际案例,帮助读者全面掌握这一技能。我们将首先介绍分页的基本概念,以及 MyBatisPlus 和 Thymeleaf 的核心功能,帮助读者理解它们如何为分页功能提供支持。本文将为读者提供一个系统的学习路径,帮助读者掌握这一重要技能。