分頁查詢是一個很常見的功能,對於分頁也有很多封裝好的輪子供我們使用。
比如使用mybatis做后端分頁可以用Pagehelper這個插件,如果使用SpringDataJPA更方便,直接就內置的分頁查詢。
做前端的分頁比如常用的Layui也用js 幫忙封裝好的分頁功能,並且只需要我們按照要求接收對應的參數就行了。
這次的文章主要是使用SpringBoot+Mybatis 實現前端后端的分頁功能,並沒有使用插件來實現,前端主要是使用Thymeleaf來渲染分頁的頁碼信息。
下面進入正式的內容部分:
加入分頁工具類
這個類主要用於存放分頁用的一些參數,可以用來接收和返回給頁面。
/**
* 封裝分頁相關的信息.
*/
public class Page {
// 當前頁碼
private int current = 1;
// 顯示上限
private int limit = 10;
// 數據總數(用於計算總頁數)
private int rows;
// 查詢路徑(用於復用分頁鏈接)
private String path;
public int getCurrent() {
return current;
}
public void setCurrent(int current) {
if (current >= 1) {
this.current = current;
}
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
if (limit >= 1 && limit <= 100) {
this.limit = limit;
}
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
if (rows >= 0) {
this.rows = rows;
}
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
/**
* 獲取當前頁的起始行
*
* @return
*/
public int getOffset() {
// current * limit - limit
return (current - 1) * limit;
}
/**
* 獲取總頁數
*
* @return
*/
public int getTotal() {
// rows / limit [+1]
if (rows % limit == 0) {
return rows / limit;
} else {
return rows / limit + 1;
}
}
/**
* 獲取起始頁碼
*
* @return
*/
public int getFrom() {
int from = current - 2;
return from < 1 ? 1 : from;
}
/**
* 獲取結束頁碼
*
* @return
*/
public int getTo() {
int to = current + 2;
int total = getTotal();
return to > total ? total : to;
}
}
控制層Controller
@RequestMapping(path = "/index", method = RequestMethod.GET)
public String getIndexPage(Model model, Page page) {
// 方法調用前,SpringMVC會自動實例化Model和Page,並將Page注入Model.
// 所以,在thymeleaf中可以直接訪問Page對象中的數據.
page.setRows(discussPostService.findDiscussPostRows(0));
page.setPath("/index");
List<DiscussPost> list = discussPostService.findDiscussPosts(0, page.getOffset(), page.getLimit());
List<Map<String, Object>> discussPosts = new ArrayList<>();
if (list != null) {
for (DiscussPost post : list) {
Map<String, Object> map = new HashMap<>();
map.put("post", post);
User user = userService.findUserById(post.getUserId());
map.put("user", user);
discussPosts.add(map);
}
}
model.addAttribute("discussPosts", discussPosts);
return "/index";
}
數據訪問層Dao:
接口Dao.java:
@Mapper
public interface DiscussPostMapper {
List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit);
// @Param注解用於給參數取別名,
// 如果只有一個參數,並且在<if>里使用,則必須加別名.
int selectDiscussPostRows(@Param("userId") int userId);
}
映射文件Mapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nowcoder.community.dao.DiscussPostMapper">
<sql id="selectFields">
id, user_id, title, content, type, status, create_time, comment_count, score
</sql>
<select id="selectDiscussPosts" resultType="DiscussPost">
select <include refid="selectFields"></include>
from discuss_post
where status != 2
<if test="userId!=0">
and user_id = #{userId}
</if>
order by type desc, create_time desc
limit #{offset}, #{limit}
</select>
<select id="selectDiscussPostRows" resultType="int">
select count(id)
from discuss_post
where status != 2
<if test="userId!=0">
and user_id = #{userId}
</if>
</select>
</mapper>
前端模板分頁邏輯
這里只是列出了分頁欄部分的邏輯,具體可以根據自己的分頁工具欄的樣式來調整。
注:
-
th:href="@{${page.path}(current=1)}這里的()內的表示傳遞的參數,也可以添加多個,如
th:href="@{${page.path}(param1=1,param2=${person.id})}" -
th:class="|page-item ${page.current==1?'disabled':''}|"這里的|表示原有的屬性,當我們要用到在原有的class添加其他class時候可以用到
<!-- 分頁 -->
<nav class="mt-5" th:if="${page.rows>0}">
<ul class="pagination justify-content-center">
<li class="page-item">
<a class="page-link" th:href="@{${page.path}(current=1)}">首頁</a>
</li>
<li th:class="|page-item ${page.current==1?'disabled':''}|">
<a class="page-link" th:href="@{${page.path}(current=${page.current-1})}">上一頁</a></li>
<li th:class="|page-item ${i==page.current?'active':''}|"
th:each="i:${#numbers.sequence(page.from,page.to)}">
<a class="page-link" th:href="@{${page.path}(current=${i})}" th:text="${i}">1</a>
</li>
<li th:class="|page-item ${page.current==page.total?'disabled':''}|">
<a class="page-link" th:href="@{${page.path}(current=${page.current+1})}">下一頁</a>
</li>
<li class="page-item">
<a class="page-link" th:href="@{${page.path}(current=${page.total})}">末頁</a>
</li>
</ul>
</nav>
附:thymeleaf遍歷,日期格式化
渲染頁面的時候會經常用到。
<!-- 帖子列表 -->
<ul class="list-unstyled">
<li class="media pb-3 pt-3 mb-3 border-bottom" th:each="map:${discussPosts}">
<a href="site/profile.html">
<img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle" alt="用戶頭像"
style="width:50px;height:50px;">
</a>
<div class="media-body">
<h6 class="mt-0 mb-3">
<a href="#" th:utext="${map.post.title}">備戰春招,面試刷題跟他復習,一個月全搞定!</a>
<span class="badge badge-secondary bg-primary" th:if="${map.post.type==1}">置頂</span>
<span class="badge badge-secondary bg-danger" th:if="${map.post.status==1}">精華</span>
</h6>
<div class="text-muted font-size-12">
<u class="mr-3" th:utext="${map.user.username}">寒江雪</u> 發布於 <b
th:text="${#dates.format(map.post.createTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-15
15:32:18</b>
<ul class="d-inline float-right">
<li class="d-inline ml-2">贊 11</li>
<li class="d-inline ml-2">|</li>
<li class="d-inline ml-2">回帖 7</li>
</ul>
</div>
</div>
</li>
</ul>
