跳到主要内容MyBatisPlus 与 Thymeleaf 全栈分页整合方案 | 极客日志Java大前端java
MyBatisPlus 与 Thymeleaf 全栈分页整合方案
前言 分页功能是提升用户体验和系统性能的关键。通过 MyBatisPlus 和 Thymeleaf 的深度整合,可以实现后端数据分页查询与前端页面渲染的无缝对接。旨在提供一个完整的全栈分页解决方案,从基础概念到具体实现,再到实际案例,帮助开发者掌握这一技能。 一、MybatisPlus 搭建及表介绍 MyBatisPlus 是一款基于 MyBatis 的增强版 ORM 框架,提供了分页插件、代…
奶糖兔79K 浏览 前言
分页功能是提升用户体验和系统性能的关键。通过 MyBatisPlus 和 Thymeleaf 的深度整合,可以实现后端数据分页查询与前端页面渲染的无缝对接。本文旨在提供一个完整的全栈分页解决方案,从基础概念到具体实现,再到实际案例,帮助开发者掌握这一技能。
一、MybatisPlus 搭建及表介绍
MyBatisPlus 是一款基于 MyBatis 的增强版 ORM 框架,提供了分页插件、代码生成器等强大功能,极大地简化了开发流程。本节介绍在 Spring Boot 中如何搭建 MyBatisPlus 的环境。
1、MybatisPlus 环境搭建
在 pom.xml 文件中增加以下依赖来引入 MybatisPlus,集成 PostgreSQL 数据库驱动包,并引入 Lombok 组件简化 Get 和 Set 方法:
<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</artifactId>
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
<version>
</version>
</dependency>
2、示例表结构介绍
这里使用城市停水信息数据为例,重点介绍如何进行数据的分页展示。其表结构如下:
二、Java 后台分页实现
本节将使用 Java 开发语言,结合 MybatisPlus 框架详细介绍在后台如何实现前端的分页需求。包含实体类实现、业务层分页实现、控制层的 API 交互。
1、实体类实现
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 分页对象来完成具体的业务。
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 集成。本节将具体介绍如何在 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 class="disabled">
<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、分页不展示
在成果页面中可以看到,正常的页面是每页展示若干条,而且表格下方带了分页条的。如果你的应用截图如下:
出现了数据全部加载的问题。那么可以看看本节的解决方案。
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 的深度整合,打造一个完整的全栈分页解决方案。从基础环境搭建到具体代码实现,再到问题排查,希望能帮助开发者全面掌握这一技能。