跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
Java大前端java

MyBatisPlus 与 Thymeleaf 全栈分页实战

基于 MyBatisPlus 和 Thymeleaf 实现全栈分页的方案。涵盖环境搭建、实体类定义、业务层分页逻辑、控制层接口设计以及前端表格与分页条的集成。通过实际案例展示如何配置分页插件解决数据加载问题,确保前后端数据交互流畅,提升系统性能与用户体验。

利刃发布于 2026/3/15更新于 2026/4/273 浏览
MyBatisPlus 与 Thymeleaf 全栈分页实战

MyBatisPlus 与 Thymeleaf 全栈分页实战

在现代应用开发中,分页功能是提升用户体验和系统性能的关键。无论是企业级应用还是面向用户的平台,高效的分页机制都能显著改善交互体验,同时降低服务器负载。本文将通过 MyBatisPlus 和 Thymeleaf 的深度整合,展示如何构建一个完整的全栈分页解决方案,实现后端数据查询与前端页面渲染的无缝对接。

一、环境搭建及表结构

MyBatisPlus 作为 MyBatis 的增强版 ORM 框架,提供了分页插件等强大功能,极大简化了开发流程。我们无需手动编写复杂的 SQL 分页逻辑,即可轻松实现高效查询。

1. 依赖配置

以 Maven 为例,在 pom.xml 中引入 MyBatisPlus、Lombok 以及 PostgreSQL 驱动包:

<!-- mybatis-plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${mybatis-plus.version}</version>
</dependency>
<!-- lombok 代码自动生成组件 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>
<!-- PostgreSql 驱动包 -->
<dependency>
    <groupId>net.postgis</groupId>
    <artifactId>postgis-jdbc</>
    2.5.0

artifactId
<version>
</version>
</dependency>

2. 示例表结构

我们以城市停水信息数据为例,重点介绍数据的分页展示。基础表结构如下:

表结构示意

对应的实例数据如下:

实例数据示意

二、Java 后台分页实现

本节结合 MyBatisPlus 框架,详细介绍如何在后台实现前端的分页需求,涵盖实体类、业务层及控制层的实现。

1. 实体类定义

实体类的实现相对简单,利用 Lombok 注解简化 Getter/Setter 方法。注意移除作者署名等无关注释:

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. 业务层分页实现

分页是查询业务的核心。MyBatisPlus 提供了 Page 对象作为基础分页组件,我们在业务接口中定义分页方法:

/**
 * - 根据区域查询分页停水信息列表
 * @param pageNum 当前页码
 * @param pageSize 每页大小
 * @param regionName 区域名称
 * @return
 */
IPage<StopWaterInfo> page(Integer pageNum, Integer pageSize, String regionName);

具体实现时,构造 QueryWrapper 设置查询条件,并传入 Page 对象:

@Override
public IPage<StopWaterInfo> page(Integer pageNum, Integer pageSize, String regionName) {
    QueryWrapper<StopWaterInfo> queryWrapper = new QueryWrapper<>();
    queryWrapper.like("regin_name", regionName);
    queryWrapper.orderByDesc("created_on");
    
    Page<StopWaterInfo> page = new Page<>(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 能够很好地与 Spring Boot 集成,提供优雅的方式构建动态 HTML 页面。本节介绍如何在 Thymeleaf 中集成后端分页,实现表格展示与分页条。

1. 分页表格展示

首先在 HTML 中定义表格结构,并通过 AJAX 从后端加载数据:

<div>
    <table>
        <thead>
            <tr>
                <th>创建时间</th>
                <th>停水地点</th>
                <th>原因</th>
            </tr>
        </thead>
        <tbody id="table-body">
            <!-- 动态内容 -->
        </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 id="table-pagination"></ul>
    </nav>
</div>

生成上一页和下一页按钮的逻辑如下(修复了原有语法错误):

function renderPagination(totalPages) {
    const paginationContainer = document.getElementById('table-pagination');
    paginationContainer.innerHTML = '';
    
    if (totalPages <= 1) return;
    
    // 上一页
    paginationContainer.innerHTML += `
        <li>
            <a href="#" onclick="changePage(${totalPages},${currentPage - 1})" aria-label="Previous">前一页</a>
        </li>
    `;
    
    // 下一页
    paginationContainer.innerHTML += `
        <li>
            <a href="#" onclick="changePage(${totalPages},${currentPage + 1})" aria-label="Next">后一页</a>
        </li>
    `;
}

3. 成果展示

最终效果如下所示,表格下方带有完整的分页导航:

成果展示

四、常见问题排查

在实现过程中,可能会遇到分页条不显示或数据全部加载的问题。

1. 现象描述

如果页面正常但缺少分页条,或者一次性加载了所有数据,通常是因为没有正确配置 MyBatisPlus 的分页插件。

问题截图

2. 解决方案

需要在后台配置分页拦截器。创建一个配置类,添加 PaginationInnerInterceptor:

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 构建全栈分页方案的完整流程。从环境搭建、实体设计到前后端交互,再到插件配置,涵盖了实际开发中的关键环节。通过合理配置分页插件,可以有效解决数据加载异常问题,确保系统性能与用户体验。

目录

  1. MyBatisPlus 与 Thymeleaf 全栈分页实战
  2. 一、环境搭建及表结构
  3. 1. 依赖配置
  4. 2. 示例表结构
  5. 二、Java 后台分页实现
  6. 1. 实体类定义
  7. 2. 业务层分页实现
  8. 3. 控制层实现
  9. 三、Thymeleaf 分页集成
  10. 1. 分页表格展示
  11. 2. 分页条集成
  12. 3. 成果展示
  13. 四、常见问题排查
  14. 1. 现象描述
  15. 2. 解决方案
  16. 五、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • URDF 与 RViz2:机器人建模基础与可视化实践
  • Fastjson 解析嵌套 JSONArray 获取值的常见陷阱与解决方案
  • PaddleNLP 3.0:实现千亿模型训推全流程的一站式解决方案
  • ionet 框架:Java 方法即 Action 的零学习成本之道
  • 激光雷达外参标定算法详解
  • 人工智能数学基础:概率论中 KL 散度在变分自编码器中的应用
  • PEEK 替代金属:人形机器人灵巧手精密注塑齿轮技术解析
  • 二分答案专题实战:木材加工与砍树问题详解
  • 精选 13 个优质编程学习资源与工具
  • ComfyUI AI 工作流抠图构建实战指南
  • AI 论文写作与降重工具功能介绍
  • VLM 经典论文综述:An Introduction to Vision-Language Modeling
  • Qwen3Guard-Gen-WEB 内容安全检测项目搭建与使用指南
  • (6-4-02)IMU融合与机体状态估计:综合实战:腿式机器人的IMU关节融合与状态估计(2)
  • GLM-4.6V-Flash-WEB 本地部署与云端 API 成本性能对比
  • 软件设计各个模块分析
  • 动态规划实战:完全背包、零钱兑换与排列组合
  • GTC 2026 前瞻:Rubin 平台与 AI 工厂化演进
  • Java 多线程核心:线程安全机制与单例模式实现
  • YOLOv8 模型部署至高通 RB5 边缘推理平台实战

相关免费在线工具

  • 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