跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Java大前端java

MyBatisPlus 与 Thymeleaf 全栈分页整合实战

基于 MyBatisPlus 与 Thymeleaf 构建全栈分页方案,涵盖环境搭建、实体类设计、业务层分页逻辑及控制层接口实现。前端采用 Ajax 动态加载数据并渲染表格与分页条,配合 MyBatisPlus 拦截器配置解决分页插件缺失问题。提供完整代码示例与常见故障排查,助力开发者快速落地高效稳定的分页功能。

DevStack发布于 2026/3/21更新于 2026/6/519 浏览
MyBatisPlus 与 Thymeleaf 全栈分页整合实战

前言

在现代 Web 开发中,分页是平衡用户体验与系统性能的关键。无论是企业级后台还是面向用户的平台,合理的分页策略能有效降低服务器负载并提升交互流畅度。本文将通过 MyBatisPlus 和 Thymeleaf 的深度整合,展示如何构建一套完整的全栈分页方案,实现后端数据查询与前端页面渲染的无缝对接。

一、环境搭建及表结构

MyBatisPlus 作为 MyBatis 的增强版 ORM 框架,内置了强大的分页插件,能大幅简化分页逻辑的开发。我们基于 Spring Boot 项目,引入必要的依赖即可快速启动。

1. 依赖配置

在 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</artifactId>
    <version>2.5.0</version>
</dependency>

2. 示例表结构

以城市停水信息为例,核心字段包括停水区域、时间、原因等。表结构设计需满足业务查询需求,确保索引优化。

二、Java 后台分页实现

后端部分主要涉及实体类定义、业务层分页逻辑及控制层接口暴露。

1. 实体类设计

使用 Lombok 简化 Getter/Setter,配合 MyBatisPlus 注解映射数据库表:

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;

    // ... 其他字段省略 ...
}

2. 业务层分页逻辑

利用 MyBatisPlus 的 IPage 对象处理分页参数,结合 QueryWrapper 构建动态查询条件:

@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 对象时传入当前页码和每页条数,直接传递给 Mapper 执行查询,无需手写 SQL 分页语句。

3. 控制层接口

Controller 接收前端请求参数,调用 Service 层方法并返回统一结果封装:

@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,但在实际 AJAX 异步加载场景中,通常由前端 JS 负责表格渲染与分页条交互。以下展示如何通过原生 JavaScript 或 jQuery 实现动态更新。

1. 表格数据渲染

定义基础 HTML 结构,通过 Ajax 获取后端 JSON 数据并填充表格:

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. 分页条交互

分页条需要支持上一页、下一页切换,并根据当前页状态禁用不可用按钮:

<div>
    <nav aria-label="Table Pagination">
        <ul id="pagination-list"></ul>
    </nav>
</div>
function renderPagination(totalPages) {
    const paginationContainer = document.getElementById('pagination-list');
    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>
    `;
}

注意修复了原代码中的标签闭合问题,确保 HTML 结构合法。

四、常见问题排查

1. 分页不生效

如果前端能看到数据但下方没有分页条,或者点击翻页无反应,通常是后端分页插件未正确配置。

2. 解决方案

检查是否注入了 MybatisPlusInterceptor 并添加了 PaginationInnerInterceptor:

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor i = new MybatisPlusInterceptor();
        i.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
        return i;
    }
}

配置完成后重启服务,分页功能即可正常运作。

五、总结

本文从环境搭建到前后端联调,完整演示了基于 MyBatisPlus 和 Thymeleaf(配合前端 JS)的全栈分页实现路径。重点解决了分页对象传递、拦截器配置及前端动态渲染等关键环节。掌握这一模式,可快速应用到各类列表查询场景中,提升开发效率与系统稳定性。

目录

  1. 前言
  2. 一、环境搭建及表结构
  3. 1. 依赖配置
  4. 2. 示例表结构
  5. 二、Java 后台分页实现
  6. 1. 实体类设计
  7. 2. 业务层分页逻辑
  8. 3. 控制层接口
  9. 三、Thymeleaf 分页集成
  10. 1. 表格数据渲染
  11. 2. 分页条交互
  12. 四、常见问题排查
  13. 1. 分页不生效
  14. 2. 解决方案
  15. 五、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 本地大模型运行工具 Ollama 安装与使用指南
  • 深入源码:Spring Bean 作用域、生命周期与自动装配
  • Spring Boot 集成 WebClient 调用第三方接口实战指南
  • 使用 Python + Flask + Tailwind 快速搭建个人博客
  • 前端文件下载实战:从原理到最佳实践
  • RAG 利用 Rerank 与两阶段检索提升检索质量
  • Vue3 前端开发常用 20 道面试题及代码解析
  • Transformer 核心机制与架构详解:注意力、自注意力及模型结构
  • 为 OpenClaw 构建双层记忆系统:QMD + Mem0 混合架构
  • WebStorm 开发卡顿优化指南
  • 主流 AI 编程模型对比与选型实战指南
  • 股票数据接口 API 实例代码 Python Java 多语言演示实时与历史数据
  • Linux 进程间通信:命名管道(FIFO)实战指南
  • C++ AIGC 模型吞吐量优化:关键参数设置与性能调优实践
  • Python 数据库连接池深度解析与调优实战
  • 基于 YOLOv8/v11 与 LLM 的 Web 目标检测及表情识别系统
  • 十大经典排序算法 Python 实现及原理详解
  • C++ 哈希表封装:模拟实现 unordered_map 与 unordered_set
  • Python 为何成为 AI 开发主流语言?对比 Java 与 Ruby
  • 本地部署大模型首选:深入解析 llama.cpp 框架

相关免费在线工具

  • 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