轉載地址:https://liuyanzhao.com/8125.html
方案二傳送陣:https://blog.csdn.net/thankna/article/details/105600475 (方案一簡化版)
方案三傳送陣:https://blog.csdn.net/thankna/article/details/105933927(方案二基礎上支持複雜sql文)
最近工作中用到,網上查資料,大部分都是代碼片段,對前後臺接口描述不詳,不方便照方抓藥。
下面這篇是我花了2天時間,在網上最完整的,我參照這個方案寫了自己的代碼,後面會放出方案二(是我自己寫的代碼)。
!!!注意:轉載這篇使用SpringBoot1.X,Spring Boot 2.0之後已經廢棄new PageRequest()方法,換用靜態方法PageRequest.of(pageNum,pageSize,Sort.Direction…..)。
SpringBoot + Spring Data JPA + Thmeleaf 分頁
一、Controller
/**
* ajax 獲取評論頁面數據
*
* @param postId
* @param model
* @return
*/
@GetMapping
public ModelAndView listComments(
@RequestParam(value = "postId") Long postId,
@RequestParam(value = "async", required = false, defaultValue = "new") Boolean async,
@RequestParam(value = "order", required = false, defaultValue = "new") String order,
@RequestParam(value = "pageIndex", required = false, defaultValue = "1") Integer pageIndex,
@RequestParam(value = "pageSize", required = false, defaultValue = "1") Integer pageSize,
Model model) {
Page<Comment> commentPage = null;
Post post = postService.getPostById(postId);
String commentOrder = "new";
try {
if (order.equals("hot")) { // 最熱查詢
Sort sort = new Sort(Sort.Direction.DESC, "zanSize", "id"); //根據點贊數量排序
Pageable pageable = new PageRequest(pageIndex - 1, pageSize, sort);
commentPage = commentService.listCommentByPost(post, pageable);
commentOrder = "hot";
} else if (order.equals("new")) { // 最新查詢
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = new PageRequest(pageIndex - 1, pageSize, sort);
commentPage = commentService.listCommentByPost(post, pageable);
}
} catch (Exception e) {
Pageable pageable = new PageRequest(0, 10);
commentPage = commentService.listCommentByPost(post, pageable);
}
Integer commentSize = post.getCommentSize();
model.addAttribute("page", commentPage);
model.addAttribute("commentSize", commentSize);
model.addAttribute("commentOrder", commentOrder);
model.addAttribute("post", post);
return new ModelAndView(async == true ? "home/post_detail :: #comment" : "home/post_detail");
}
二、HTML 代碼
1、post_detail.html
本項目使用了 Spring Security ,開啓了 CSRF 防護,所以需要在 head 裏引入
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
這是 Thymeleaf 的替換標籤
<!--分頁-->
<div th:replace="~{home/fragments/page :: header-page}"></div>
<!--/分頁-->
頁面底部,引入 JS,將文章的id postId 傳到 js 裏
<script th:inline="javascript">
var postId = [[${post.id}]];
var postUrl = '/' + [[${post.user.username}]] + '/posts/' + [[${post.id}]];
</script>
page.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>分頁</title>
</head>
<body>
<div data-th-fragment="header-page">
<div class="header-page paging-box"
th:if="${(page.totalPages gt 0) && (page.totalPages le 7)}"
data-th-attr="data-order=${commentOrder}">
<span class="result">共[[${page.totalPages}]]頁</span>
<a href="javascript:void(0)" class="page-link prev"
th:classappend="${page.first?'disabled':''}"
data-th-attr="pageIndex=${page.number}">上一頁</a>
<a href="javascript:void(0)" class="page-link"
th:classappend="${(page.number+1) eq i} ?'current':''"
th:each="i: ${#numbers.sequence(1, page.totalPages)}"
data-th-attr="pageIndex=${i}">[[${i}]]</a>
<a href="javascript:void(0)" class="page-link next"
th:classappend="${page.last?'disabled':''}"
data-th-attr="pageIndex=${page.number+2}">下一頁</a>
</div>
<div class="header-page paging-box"
th:if="${page.totalPages gt 7}"
data-th-attr="data-order=${commentOrder}">
<span class="result">共[[${page.totalPages}]]頁</span>
<!--上一頁-->
<a href="javascript:void(0)" class="page-link prev"
th:classappend="${page.first?'disabled':''}"
data-th-attr="pageIndex=${page.number}">上一頁</a>
<!--首頁-->
<a href="javascript:void(0)" class="page-link"
th:classappend="${(page.number+1) eq 1} ?'current':''"
data-th-attr="pageIndex=1">
1
</a>
<!-- 當前頁面小於等於4 -->
<a href="javascript:void(0)" class="page-link"
th:if="${(page.number+1) le 4}"
th:classappend="${(page.number+1) eq i} ?'current':''"
data-th-each="i : ${#numbers.sequence(2,5)}"
data-th-attr="pageIndex=${i}">[[${i}]]</a>
<span class="dian" data-th-if="${(page.number + 1) le 4}">...</span>
<!-- 最後一頁與當前頁面之差,小於等於3 -->
<span class="dian"
data-th-if="${(page.totalPages-(page.number + 1)) le 3}">...</span>
<a href="javascript:void(0)" class="page-link"
th:if="${(page.totalPages-(page.number + 1)) le 3}"
th:classappend="${(page.number+1) eq i} ?'current':''"
th:each="i : ${#numbers.sequence(page.totalPages-4, page.totalPages-1)}"
data-th-attr="pageIndex=${i}">[[${i}]]</a>
<!-- 最後一頁與當前頁面之差大於3,且當前頁面大於4-->
<span class="dian"
data-th-if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}">...</span>
<a href="javascript:void(0)" class="page-link"
th:if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}"
data-th-attr="pageIndex=${page.number}">[[${page.number}]]</a>
<a href="javascript:void(0)" class="page-link current"
th:if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}"
data-th-attr="pageIndex=${page.number+1}">[[${page.number
+1 }]]</a>
<a href="javascript:void(0)" class="page-link"
th:if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}"
data-th-attr="pageIndex=${page.number+2}">[[${page.number
+2 }]]</a>
<span class="dian" data-th-if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}">...</span>
<!--尾頁-->
<a href="javascript:void(0)" class="page-link"
th:classappend="${(page.number+1) eq page.totalPages} ?'current':''"
data-th-attr="pageIndex=${page.totalPages}">
[[${page.totalPages}]]
</a>
<!--下一頁-->
<a href="javascript:void(0)" class="page-link next"
th:classappend="${page.last?'disabled':''}"
data-th-attr="pageIndex=${page.number+2}">下一頁</a>
</div>
</div>
<div data-th-fragment="bottom-page">
<div class="bottom-page paging-box-big" th:if="${(page.totalPages gt 0) && (page.totalPages le 7)}"
data-th-attr="data-order=${commentOrder}">
<a href="javascript:void(0)" class="page-link prev"
th:classappend="${page.first?'disabled':''}"
data-th-attr="pageIndex=${page.number}">上一頁</a>
<a href="javascript:void(0)" class="page-link"
th:classappend="${(page.number+1) eq i} ?'current':''"
th:each="i: ${#numbers.sequence(1, page.totalPages)}"
data-th-attr="pageIndex=${i}">[[${i}]]</a>
<a href="javascript:void(0)" class="page-link next"
th:classappend="${page.last?'disabled':''}"
data-th-attr="pageIndex=${page.number+2}">下一頁</a>
<div class="page-jump">共<span>[[${page.totalPages}]]</span>頁,跳至
<input type="number" class="jump-page-size" th:max="${page.totalPages}">頁
</div>
</div>
<div class="bottom-page paging-box-big"
th:if="${page.totalPages gt 7}"
data-th-attr="data-order=${commentOrder}">
<!--上一頁-->
<a href="javascript:void(0)" class="page-link prev"
th:classappend="${page.first?'disabled':''}"
data-th-attr="pageIndex=${page.number}">上一頁</a>
<!--首頁-->
<a href="javascript:void(0)" class="page-link"
th:classappend="${(page.number+1) eq 1} ?'current':''"
data-th-attr="pageIndex=1">
1
</a>
<!-- 當前頁面小於等於4 -->
<a href="javascript:void(0)" class="page-link"
th:if="${(page.number+1) le 4}"
th:classappend="${(page.number+1) eq i} ?'current':''"
data-th-each="i : ${#numbers.sequence(2,5)}"
data-th-attr="pageIndex=${i}">[[${i}]]</a>
<span class="dian" data-th-if="${(page.number + 1) le 4}">...</span>
<!-- 最後一頁與當前頁面之差,小於等於3 -->
<span class="dian"
data-th-if="${(page.totalPages-(page.number + 1)) le 3}">...</span>
<a href="javascript:void(0)" class="page-link"
th:if="${(page.totalPages-(page.number + 1)) le 3}"
th:classappend="${(page.number+1) eq i} ?'current':''"
th:each="i : ${#numbers.sequence(page.totalPages-4, page.totalPages-1)}"
data-th-attr="pageIndex=${i}">[[${i}]]</a>
<!-- 最後一頁與當前頁面之差大於3,且當前頁面大於4-->
<span class="dian"
data-th-if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}">...</span>
<a href="javascript:void(0)" class="page-link"
th:if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}"
data-th-attr="pageIndex=${page.number}">[[${page.number}]]</a>
<a href="javascript:void(0)" class="page-link current"
th:if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}"
data-th-attr="pageIndex=${page.number+1}">[[${page.number
+1 }]]</a>
<a href="javascript:void(0)" class="page-link"
th:if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}"
data-th-attr="pageIndex=${page.number+2}">[[${page.number
+2 }]]</a>
<span class="dian" data-th-if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}">...</span>
<!--尾頁-->
<a href="javascript:void(0)" class="page-link"
th:classappend="${(page.number+1) eq page.totalPages} ?'current':''"
data-th-attr="pageIndex=${page.totalPages}">
[[${page.totalPages}]]
</a>
<!--下一頁-->
<a href="javascript:void(0)" class="page-link next"
th:classappend="${page.last?'disabled':''}"
data-th-attr="pageIndex=${page.number+2}">下一頁</a>
<div class="page-jump">共<span>[[${page.totalPages}]]</span>頁,跳至
<input type="number" name="pageIndex" class="jump-page-size" min="1" th:max="${page.totalPages}">頁
</div>
</div>
<script>
var pageIndex = [[${page.number+1}]]
</script>
</div>
</body>
</html>
因爲很多頁面都要使用分頁,所以完全可以把分頁的代碼剝離出來,公共使用。只需要將分頁的數據的 model 寫成 page 就行。這裏分頁分成了兩種,一種是分頁少於等於7個的,我們直接顯示 1234567;另一種是大於7 的,則中間以..分隔。
三、JS 代碼
$(function () {
// 獲取評論列表
function getComment(postId, pageIndex, order) {
var _ctx = $("meta[name='ctx']").attr("content");
// 獲取 CSRF Token
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$.ajax({
url: _ctx + '/comments',
type: 'GET',
data: {
"async": true,
"postId": postId,
"pageIndex": pageIndex,
"order": order
},
beforeSend: function (request) {
request.setRequestHeader(header, token); // 添加 CSRF Token
},
success: function (data) {
$("#comment-wrapper").html(data);
},
error: function () {
layer.msg("出現錯誤,請嘗試刷新頁面!", {icon: 2, anim: 6});
}
});
};
//切換評論排序規則
$(document).on('click', '.tabs-order .new-sort', function () {
var pageIndex = $(this).attr("pageIndex");
getComment(postId, pageIndex, "new");
});
$(document).on('click', '.tabs-order .hot-sort', function () {
var pageIndex = $(this).attr("pageIndex");
getComment(postId, pageIndex, "hot");
});
//分頁獲取評論列表
$(document).on('click', '.tcd-number', function () {
var order = $(this).parents(".paging-box").attr("data-order");
if ($(this).hasClass('current')) {
return false;
}
var pageIndex = $(this).attr("pageIndex");
getComment(postId, pageIndex, order);
});
//跳轉到指定的頁號
$(document).on('keydown', '.jump-page-size', function (event) {
var max = parseInt($(this).attr("max"));
var pageIndex = parseInt($(this).val());
var order = $('.paging-box').attr('data-order');
if (event.keyCode == "13") {//keyCode=13是回車鍵
if (pageIndex == "" || pageIndex == null) {
return false;
}
if (!/^\d+$/.test(pageIndex)) {
pageIndex = 1;
}
if (pageIndex < 1) {
pageIndex = 1;
}
if (pageIndex > max) {
pageIndex = max;
}
getComment(postId, pageIndex, order);
}
})
// 初始化 博客評論列表
getComment(postId, 1, "new");
})
四、CSS 代碼
爲了方便大家的使用,這裏同時提供 CSS 代碼。
注:本模板是扒自嗶哩嗶哩,侵刪
page.css
.paging-box {
font-size: 12px
}
.paging-box .disabled {
cursor: not-allowed
}
.paging-box .current, .paging-box .dian, .paging-box .next, .paging-box .prev, .paging-box .tcd-number {
color: #222;
cursor: pointer;
text-align: center;
margin: 0 4px;
text-decoration: none;
line-height: 26px
}
.paging-box .current:hover, .paging-box .dian:hover, .paging-box .next:hover, .paging-box .prev:hover, .paging-box .tcd-number:hover {
color: #00a1d6
}
.paging-box .current {
color: #00a1d6;
font-weight: 700
}
.paging-box .dian {
cursor: default
}
.paging-box .dian:hover {
color: #222
}
.paging-box .result {
padding-right: 10px
}
.paging-box-big {
font-size: 12px
}
.paging-box-big .disabled {
display: none
}
.paging-box-big .current, .paging-box-big .dian, .paging-box-big .next, .paging-box-big .prev, .paging-box-big .tcd-number {
color: #222;
cursor: pointer;
text-align: center;
border-radius: 4px;
background-color: #fff;
border: 1px solid #ddd;
background-image: none;
transition: all .2s;
font-size: 14px;
min-width: 15px;
margin: 0 2px;
padding: 0 13px;
display: inline-block;
height: 36px;
line-height: 36px;
text-decoration: none
}
.paging-box-big .current, .paging-box-big .current:hover, .paging-box-big .dian:hover, .paging-box-big .next:hover, .paging-box-big .prev:hover, .paging-box-big .tcd-number:hover {
background: #00a1d6;
color: #fff;
border: 1px solid #00a1d6
}
.paging-box-big .dian {
cursor: default;
border-color: #fff
}
.paging-box-big .dian:hover {
background: #fff;
color: #222;
border: 1px solid #fff
}
.paging-box-big .next, .paging-box-big .prev {
padding: 0 15px
}
.paging-box-big .page-jump {
float: rightright;
color: #99a2aa;
line-height: 36px
}
.paging-box-big .page-jump input {
margin: 0 5px;
padding: 0 2px;
height: 24px;
line-height: 24px;
margin-top: 7px;
font-size: 12px;
box-shadow: none;
width: 40px;
border-radius: 4px;
border: 1px solid #ddd;
outline: 0;
text-align: center
}
.paging-box-big .page-jump input:focus {
border-color: #00a1d6
}
五、補充
1、Spring Data JPA 提供了分頁器,可以直接使用。
/**
* 根據文章獲取評論,分頁顯示
*
* @param post
* @param pid
* @return
*/
Page<Comment> findByPostAndPid(Post post, Long pid, Pageable pageable);
其中 pageable 可以通過創建 PageRequest 對象獲得,需要傳入 page 頁碼,size 一頁顯示數量。sort 是排序規則,相當於 sql 語句裏的 order by,可選。
Sort sort = new Sort(Sort.Direction.DESC, "zanSize", "id");
Pageable pageable = new PageRequest(pageIndex - 1, pageSize, sort);
2、將現成 List 轉成 Page,也可以這樣
List<Comment> commentList = post.getCommentList()
PageRequest pageRequest = new PageRequest(pageIndex,pageSize);
Page<Comment> commentPage = new PageImpl<Comment>(commentList,pageRequest,commentList.size());
3、page 對象的幾個屬性
總共頁數:${userDTOPage.totalPages}
記錄總數:${userDTOPage.totalElements}
當前頁號:${userDTOPage.number}
是否爲首頁:${userDTOPage.first}
是否爲尾頁:${userDTOPage.last}
每頁顯示的數量:${userDTOPage.numberOfElements}
END
這篇沒有GitHub代碼。代碼都在文案上,大家自己複製吧。