简单的前端分页展示功能:以表格的方式展现每页数据,在表格标题下填入对应的字段值,页脚处显示当前页、总记录页数和条数,一键跳转至首尾页和相邻页。在页眉处按照始末时间查询记录。
在控制层需要返回给前端的 model 属性有分页对象 pageInfo,数据 records;另外,由于按照时间查询后,需要在前端页面中填充时间,所以把 startTime 和 endTime 也添加到 model 的属性里。
@GetMapping("test/records")
public String getRecordsAndPageInfoBetweenTime(String startTime, String endTime, Model model,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
startTime = TimeUtils.toNull(startTime);
endTime = TimeUtils.toNull(endTime);
PageInfo<ApiTestRecordVO> pageInfo = apiTestRecordService.getPageInfoBetweenTime(startTime, endTime, pageNum, pageSize);
model.addAttribute("pageInfo", pageInfo);
model.addAttribute("startTime", startTime);
model.addAttribute("endTime", endTime);
return "test-records";
}
控制层使用到的工具类 TimeUtils 中的 toNull 方法
public static String toNull(String time) {
if (StringUtils.equalsIgnoreCase(time, "null") || StringUtils.isBlank(time)) {
return null;
}
return time;
}
@Override
public PageInfo<ApiTestRecordVO> getPageInfoBetweenTime(String startTime, String endTime, Integer pageNum, Integer pageSize) {
if (pageNum == null || pageNum <= 0) {
pageNum = DEFAULT_PAGE_NUM;
}
if (pageSize == null || pageSize <= 5) {
pageSize = DEFAULT_PAGE_SIZE;
}
return new PageInfo<>(getRecordsBetweenTimeByPage(startTime, endTime, pageNum, pageSize), DEFAULT_NAVIGATE_PAGES);
}
private List<ApiTestRecordVO> getRecordsBetweenTimeByPage(String startTime, String endTime, Integer pageNum, Integer pageSize) {
PageHelper.startPage(pageNum, pageSize);
startTime = TimeUtils.getNormalizedInputTime(startTime);
endTime = TimeUtils.getNormalizedInputTime(endTime);
return apiTestRecordMapper.getApiTestRecordVOsBetweenTime(startTime, endTime);
}
控制层使用到的工具类 TimeUtils 中的 getNormalizedInputTime 方法,将前端 input 输入框中的日期格式 yyyy-MM-ddTHH:mm
改为 yyyy-MM-dd HH:mm
,以便于作为将日期字符串作为 MySQL 的查询条件。
public static String getNormalizedInputTime(String inputTime) {
return StringUtils.replaceChars(inputTime, 'T', ' ');
}
持久层的代码为 MyBatis 的 mapper 接口 + xml 配置,比较简单,此处不予赘述。
数据展示部分,以表格形式展示,本文引入 Bootstrap CSS 做页面美化。在 tr 标签中对 records 做 Thymealeaf each 遍历,可以将根据数据大小动态添加表格行,在 td 标签中一一添加每个 record 对象的字段值。
<table class="table">
<thead>
<tr>
<th>系统th>
<th>环境th>
<th>方法th>
<th>协议th>
<th>URLth>
<th>参数th>
<th>期望返回值th>
<th>测试时间th>
<th>是否通过th>
tr>
thead>
<tbody>
<tr th:each="record:${pageInfo.list}">
<td th:text="${record.system}">td>
<td th:text="${record.environment}">td>
<td th:text="${record.method}">td>
<td th:text="${record.protocol}">td>
<td th:text="${record.url}">td>
<td th:text="${record.paramStr}">td>
<td th:text="${record.expectedContain}">td>
<td th:text="${record.testTime}">td>
<td th:text="${record.passed}">td>
tr>
tbody>
table>
在无序列表使用 pagination 类来使其变为一个标准的页码导航栏,在 li 标签中利用 Thymeleaf 的变量表达式对后端返回的 pageInfo的属性做判断、遍历、文本或 href 填充等。
<div class="modal-footer">
<div class="col-md-6">
当前第 [[${pageInfo.pageNum}]] 页,共 [[${pageInfo.pages}]] 页,[[${pageInfo.total}]] 条记录
div>
<ul class="pagination">
<li class="page-link" th:if="${pageInfo.hasPreviousPage}">
<a th:href="'/api/test/records?startTime='+${startTime}+'&endTime='+${endTime}+'&pageNum=1'">首页a>
li>
<li class="page-link" th:if="${pageInfo.hasPreviousPage}">
<a th:href="'/api/test/records?startTime='+${startTime}+'&endTime='+${endTime}+'&pageNum='+${pageInfo.prePage}">上一页a>
li>
<li class="page-link" th:each="nav:${pageInfo.navigatepageNums}">
<a th:href="'/api/test/records?startTime='+${startTime}+'&endTime='+${endTime}+'&pageNum='+${nav}"
th:text="${nav}" th:if="${nav != pageInfo.pageNum}">a>
<span style="font-weight: bold;background: lightskyblue;" th:if="${nav == pageInfo.pageNum}"
th:text="${nav}">span>
li>
<li class="page-link" th:if="${pageInfo.hasNextPage}">
<a th:href="'/api/test/records?startTime='+${startTime}+'&endTime='+${endTime}+'&pageNum='+${pageInfo.nextPage}">下一页a>
li>
<li class="page-link" th:if="${pageInfo.pageNum < pageInfo.pages}">
<a th:href="'/api/test/records?startTime='+${startTime}+'&endTime='+${endTime}+'&pageNum='+${pageInfo.pages}">尾页a>
li>
ul>
div>
从分页导航栏的代码可以看出 PageInfo 对象的强大,其中封装了以下属性:
属性 | 作用 |
---|---|
pageNum | 当前页 |
pages | 总页数 |
total | 总记录数 |
hasPreviousPage | 是否有上一页 |
prePage | 上一页 |
navigatepageNums | 导航页码数组 |
hasNextPage | 是否有下一页 |
nextPage | 下一页 |
这些属性与 Thymealeaf 的变量表达式结合,共同构成了如下图所示的导航功能:
在表格上方加上按时间搜索表单
<form class="form-check-inline" action="/api/test/records">
<label for="startTime" class="form-check-label">起始时间:label><input name="startTime" id="startTime"
type="datetime-local" th:value="${startTime}">
<label for="endTime" class="form-check-label">结束时间:label><input name="endTime" id="endTime" type="datetime-local"
th:value="${endTime}">
<input type="submit" class="btn-outline-primary" value="按时间查询"/>
form>
注意,按时间搜索后,要把填入的时间回写到 input datetime-local
标签内。
本文的核心在于充分利用了 PageInfo 强大的分页功能,其中封装了诸多便于做导航栏页码展示的字段。再结合 Spring Boot 官方推荐的前后端不分离的框架 Thymeleaf 将 Spring UI Model 中的属性渲染到页面上。
本文源码参考:SpringBoot+PageHelper+Bootstrap+Thymeleaf 实现分页功能