日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java Web -【分页功能】详解

發(fā)布時(shí)間:2025/3/21 java 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Web -【分页功能】详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

分頁簡(jiǎn)介

分頁功能在網(wǎng)頁中是非常常見的一個(gè)功能,其作用也就是將數(shù)據(jù)分割成多個(gè)頁面來進(jìn)行顯示。

  • 使用場(chǎng)景: 當(dāng)取到的數(shù)據(jù)量達(dá)到一定的時(shí)候,就需要使用分頁來進(jìn)行數(shù)據(jù)分割。

當(dāng)我們不使用分頁功能的時(shí)候,會(huì)面臨許多的問題:

  • 客戶端的問題: 如果數(shù)據(jù)量太多,都顯示在同一個(gè)頁面的話,會(huì)因?yàn)轫撁嫣L(zhǎng)嚴(yán)重影響到用戶的體驗(yàn),也不便于操作,也會(huì)出現(xiàn)加載太慢的問題。
  • 服務(wù)端的問題: 如果數(shù)據(jù)量太多,可能會(huì)造成內(nèi)存溢出,而且一次請(qǐng)求攜帶的數(shù)據(jù)太多,對(duì)服務(wù)器的性能也是一個(gè)考驗(yàn)。

分頁的分類

分頁的實(shí)現(xiàn)分為真分頁和假分頁兩種,也就是物理分頁和邏輯分頁。

1.真分頁(物理分頁):

  • 實(shí)現(xiàn)原理: SELECT * FROM xxx [WHERE...] LIMIT #{param1}, #{param2}
    第一個(gè)參數(shù)是開始數(shù)據(jù)的索引位置
    第二個(gè)參數(shù)是要查詢多少條數(shù)據(jù)
  • 優(yōu)點(diǎn): 不會(huì)造成內(nèi)存溢出
  • 缺點(diǎn): 翻頁的速度比較慢

2.假分頁(邏輯分頁):

  • 實(shí)現(xiàn)原理: 一次性將所有的數(shù)據(jù)查詢出來放在內(nèi)存之中,每次需要查詢的時(shí)候就直接從內(nèi)存之中去取出相應(yīng)索引區(qū)間的數(shù)據(jù)
  • 優(yōu)點(diǎn): 分頁的速度比較快
  • 缺點(diǎn): 可能造成內(nèi)存溢出

傳統(tǒng)的分頁方式

對(duì)于假分頁的實(shí)現(xiàn)方式很簡(jiǎn)單,只需要準(zhǔn)備一個(gè)集合保存從數(shù)據(jù)庫中取出的所有數(shù)據(jù),然后根據(jù)當(dāng)前頁面的碼數(shù),取出對(duì)應(yīng)范圍的數(shù)據(jù)顯示就好了,我們這里基于物理分頁來實(shí)現(xiàn)。

分頁的原理

  • 頁面中的數(shù)據(jù)有:
    結(jié)果集:通過 SQL 語句查詢得來的——List<Student>
  • 分頁條中的數(shù)據(jù)有:
    當(dāng)前頁:用戶傳遞到后臺(tái)——currentPage
    總頁數(shù):計(jì)算的來——totalPage
    上一頁:計(jì)算的來——prePage
    下一頁:計(jì)算的來——nextPage
    尾頁:計(jì)算的來(總頁數(shù))——lastPage
    頁面大小(即每一頁顯示的條數(shù)):用戶傳遞到后臺(tái)——count
    總條數(shù):通過 SQL 語句查詢得來的——totalCount

可以發(fā)現(xiàn)頁面功能中需要用到的數(shù)據(jù)有兩個(gè)是需要通過 SQL 語句查詢得來的:一個(gè)是頁面中顯示的數(shù)據(jù) List<Student> ,另一個(gè)是數(shù)據(jù)的總條數(shù) totalCount,分別對(duì)應(yīng)以下兩條 SQL 語句:

  • SELECT * FROM student LIMIT #{param1}, #{param2}
  • SELECT COUNT(*) FROM student

通過計(jì)算得到的數(shù)據(jù)有:

  • 總頁數(shù):totalPage
    總頁數(shù) = 總條數(shù) % 頁面大小 == 0 ? 總條數(shù) / 頁面大小 : 總條數(shù) / 頁面大小 + 1
  • 上一頁:prePage
    上一頁 = 當(dāng)前頁 - 1 > = 1 ? 當(dāng)前頁 - 1 : 1
  • 下一頁:nextPage
    下一頁 = 當(dāng)前頁 + 1 <= totalPage ? 當(dāng)前頁 + 1 : totalPage
  • 尾頁:lastPage
    尾頁 = 總條數(shù) % 頁面大小 == 0 ? 總條數(shù) - 頁面大小 : 總條數(shù) - 總條數(shù) % 頁面大小

用戶傳遞的數(shù)據(jù):

  • 當(dāng)前頁:currentPage
  • 頁面大小:count

所有我們可以創(chuàng)建一個(gè) Page 工具類備用:

public class Page {int start; // 開始數(shù)據(jù)的索引int count; // 每一頁的數(shù)量int total; // 總共的數(shù)據(jù)量/*** 提供一個(gè)構(gòu)造方法* @param start* @param count*/ public Page(int start, int count) {super();this.start = start;this.count = count;}/*** 判斷是否有上一頁* @return*/public boolean isHasPreviouse(){if(start==0)return false;return true;}/*** 判斷是否有下一頁* @return*/public boolean isHasNext(){if(start==getLast())return false;return true;}/*** 計(jì)算得到總頁數(shù)* @return*/public int getTotalPage(){int totalPage;// 假設(shè)總數(shù)是50,是能夠被5整除的,那么就有10頁if (0 == total % count)totalPage = total /count;// 假設(shè)總數(shù)是51,不能夠被5整除的,那么就有11頁elsetotalPage = total / count + 1;if(0==totalPage)totalPage = 1;return totalPage;}/*** 計(jì)算得到尾頁* @return*/public int getLast(){int last;// 假設(shè)總數(shù)是50,是能夠被5整除的,那么最后一頁的開始就是45if (0 == total % count)last = total - count;// 假設(shè)總數(shù)是51,不能夠被5整除的,那么最后一頁的開始就是50elselast = total - total % count;last = last<0?0:last;return last;}/* getter and setter */ }

前臺(tái)實(shí)現(xiàn)分頁設(shè)計(jì)

首先我們?cè)谇芭_(tái)需要完成我們分頁條的設(shè)計(jì),這里可以直接引入 Bootstrap 來完成:

上面是使用 Bootstrap 實(shí)現(xiàn)一個(gè)分頁條的簡(jiǎn)單例子,如果不熟悉的童鞋可以去菜鳥教程中查看:點(diǎn)這里


簡(jiǎn)單版本的分頁條

為了便于理解,我們先來實(shí)現(xiàn)一個(gè)簡(jiǎn)單版本的分頁條吧:

  • 首頁超鏈:指向了 start 為 0 的首頁
<li><a href="?page.start=0"><span>?</span></a> </li>
  • 上一頁超鏈:
<li ><a href="?page.start=${page.start-page.count}"><span>?</span></a> </li>
  • 下一頁超鏈:
<li ><a href="?page.start=${page.start+page.count}"><span>?</span></a> </li>
  • 最后一頁超鏈:指向了最后一頁
<li ><a href="?page.start=${page.last}"><span>?</span></a> </li>
  • 中間頁:
<c:forEach begin="0" end="${page.totalPage-1}" varStatus="status"><li><a href="?page.start=${status.index*page.count}" class="current">${status.count}</a></li> </c:forEach>
  • 所以寫完看起來會(huì)是這樣子的:
<nav><ul class="pagination"><li><a href="?page.start=0"><span>?</span></a></li><li ><a href="?page.start=${page.start-page.count}"><span>?</span></a></li><c:forEach begin="0" end="${page.totalPage-1}" varStatus="status"><li><a href="?page.start=${status.index*page.count}" class="current">${status.count}</a></li></c:forEach><li ><a href="?page.start=${page.start+page.count}"><span>?</span></a></li><li ><a href="?page.start=${page.last}"><span>?</span></a></li></ul> </nav>
  • 存在的問題:
    ① 沒有邊界判斷,即在首頁仍然可以點(diǎn)擊前一頁,不符合邏輯也影響用戶體驗(yàn)
    ② 會(huì)顯示完所有的分頁,即如果 totalPage 有50頁,那么分頁欄將會(huì)顯得特別長(zhǎng),影響體驗(yàn)

改良版本的分頁條

1.寫好頭和尾

<nav class="pageDIV"><ul class="pagination">.....</ul> </nav>

2.寫好? ?這兩個(gè)功能按鈕
使用 <c:if>標(biāo)簽來增加邊界判斷,如果沒有前面的頁碼了則設(shè)置為disable狀態(tài)

<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>><a href="?page.start=0"><span>?</span></a></li><li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>><a href="?page.start=${page.start-page.count}"><span>?</span></a></li>

再通過 JavaScrip 代碼來完成禁用功能:

<script>$(function () {$("ul.pagination li.disabled a").click(function () {return false;});}); </script>

3.完成中間頁碼的編寫

<c:forEach begin="0" end="${page.totalPage-1}" varStatus="status"><c:if test="${status.count*page.count-page.start<=30 && status.count*page.count-page.start>=-10}"><li <c:if test="${status.index*page.count==page.start}">class="disabled"</c:if>><ahref="?page.start=${status.index*page.count}"<c:if test="${status.index*page.count==page.start}">class="current"</c:if>>${status.count}</a></li></c:if> </c:forEach>

從 0 循環(huán)到 page.totalPage - 1 ,varStatus 相當(dāng)于是循環(huán)變量

  • status.count 是從1開始遍歷
  • status.index 是從0開始遍歷
  • 要求:顯示當(dāng)前頁碼的前兩個(gè)和后兩個(gè)就可,例如當(dāng)前頁碼為3的時(shí)候,就顯示 1 2 3(當(dāng)前頁) 4 5 的頁碼
  • 理解測(cè)試條件:
    -10 <= 當(dāng)前頁*每一頁顯示的數(shù)目 - 當(dāng)前頁開始的數(shù)據(jù)編號(hào) <= 30

  • 只要理解了這個(gè)判斷條件,其他的就都好理解了
  • 注意: 測(cè)試條件是需要根據(jù)項(xiàng)目的需求動(dòng)態(tài)改變的,不是萬能的!

后臺(tái)中的分頁

首頁在項(xiàng)目中引入上面提到的 Page 工具類,然后我們?cè)?DAO 類中使用 LIMIT 關(guān)鍵字來查詢數(shù)據(jù)庫中的信息:

public List<Student> list() {return list(0, Short.MAX_VALUE); }public List<Student> list(int start, int count) {List<Student> students = new ArrayList<>();String sql = "SELECT * FROM student ORDER BY student_id desc limit ?,?";try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql)) {ps.setInt(1, start);ps.setInt(2, count);// 獲取結(jié)果集...} catch (SQLException e) {e.printStackTrace();}return students; }

在 Servlet 中獲取分頁參數(shù)并使首頁顯示的 StudentList 用 page 的參數(shù)來獲取:

// 獲取分頁參數(shù) int start = 0; int count = 10;try {start = Integer.parseInt(req.getParameter("page.start"));count = Integer.parseInt(req.getParameter("page.count")); } catch (Exception e) { } Page page = new Page(start, count);List<Student> students = studentDAO.list(page.getStart(), page.getCount());....// 共享數(shù)據(jù) req.setAttribute("page", page); req.setAttribute("students", students);

以上即可完成分頁功能,但這是基于 Servlet 的版本,在之前寫過的項(xiàng)目(學(xué)生管理系統(tǒng)(簡(jiǎn)易版))中實(shí)際的使用了這種方法,感興趣的可以去看一下。


SSM 中的分頁

在 SSM 項(xiàng)目中,我們可以使用 MyBatis 的一款分頁插件: PageHelper 來幫助我們更加簡(jiǎn)單的完成分頁的需求,官網(wǎng)在這里: PageHelper

在這里,我們演示一下如何使用上面的工具重構(gòu)我們之前寫過的 SSM 項(xiàng)目 —— 學(xué)生管理系統(tǒng)-SSM 版

第一步:添加相關(guān) jar 依賴包

PageHelper 需要依賴兩個(gè) jar 包,我們直接在 pom.xml 中增加兩個(gè) jar 包依賴:

<!-- pageHelper --> <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.2-beta</version> </dependency><!--jsqlparser--> <dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>1.0</version> </dependency>

第二步:配置相關(guān)環(huán)境

在 MyBatis 的 SessionFactory 配置中新增加一個(gè)屬性名 plugins 的配置:

<!-- 配置SqlSessionFactory對(duì)象 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 注入數(shù)據(jù)庫連接池 --><property name="dataSource" ref="dataSource"/><!-- 掃描entity包 使用別名 --><property name="typeAliasesPackage" value="cn.wmyskxz.entity"/><!-- 掃描sql配置文件:mapper需要的xml文件 --><property name="mapperLocations" value="classpath:mapper/*.xml"/><!-- 讓MyBatis支持PageHelper插件 --><property name="plugins"><array><bean class="com.github.pagehelper.PageInterceptor"><property name="properties"><!--使用下面的方式配置參數(shù),一行配置一個(gè) --><value></value></property></bean></array></property> </bean>

第三步:重構(gòu)項(xiàng)目

首先我們把 LIMIT 關(guān)鍵字從映射文件中干掉:

<!-- 查詢從start位置開始的count條數(shù)據(jù)--> <select id="list" resultMap="student">SELECT * FROM student ORDER BY student_id desc </select>

然后注釋掉查詢數(shù)據(jù)總條數(shù)的 SQL 語句:

<!--&lt;!&ndash; 查詢數(shù)據(jù)條目 &ndash;&gt;--> <!--<select id="getTotal" resultType="int">--><!--SELECT COUNT(*) FROM student--> <!--</select>-->

在 Dao 類和 Service 類中修改相應(yīng)的地方:

然后修改掉 StudentController 中的方法:

@RequestMapping("/listStudent") public String listStudent(HttpServletRequest request, HttpServletResponse response) {// 獲取分頁參數(shù)int start = 0;int count = 10;try {start = Integer.parseInt(request.getParameter("page.start"));count = Integer.parseInt(request.getParameter("page.count"));} catch (Exception e) {}Page page = new Page(start, count);// 使用 PageHelper 來設(shè)置分頁P(yáng)ageHelper.offsetPage(page.getStart(),page.getCount());List<Student> students = studentService.list();// 使用 PageHelper 來獲取總數(shù)int total = (int) new PageInfo<>(students).getTotal();page.setTotal(total);request.setAttribute("students", students);request.setAttribute("page", page);return "listStudent"; }

重啟服務(wù)器,能看到也能夠正確的使用分頁功能。

總結(jié)

其實(shí)我自己對(duì)于這個(gè)工具比較無感..因?yàn)橹皇侨趸松僖徊糠值墓δ?#xff0c;并沒有我想象中的那樣 “智能” ,也沒有看到什么好的博文能夠點(diǎn)通我的認(rèn)知,希望了解的大大們能無私分享一下,謝謝!

歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處!
簡(jiǎn)書ID:@我沒有三顆心臟



作者:我沒有三顆心臟
鏈接:https://www.jianshu.com/p/d108d0cd9acf
來源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

總結(jié)

以上是生活随笔為你收集整理的Java Web -【分页功能】详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。