(一)需求
簡單的前端分頁展示功能:以表格的方式展現每頁數據,在表格標題下填入對應的字段值,頁腳處顯示當前頁、總記錄頁數和條數,一鍵跳轉至首尾頁和相鄰頁。在頁眉處按照始末時間查詢記錄。
(二)代碼
2.1 後端代碼
控制層
在控制層需要返回給前端的 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 配置,比較簡單,此處不予贅述。
2.2 前端代碼
動態表格
數據展示部分,以表格形式展示,本文引入 Bootstrap CSS 做頁面美化。在 tr 標籤中對 records 做 Thymealeaf each 遍歷,可以將根據數據大小動態添加表格行,在 td 標籤中一一添加每個 record 對象的字段值。
<table class="table">
<thead>
<tr>
<th>系統</th>
<th>環境</th>
<th>方法</th>
<th>協議</th>
<th>URL</th>
<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 實現分頁功能