分頁
在開發中我們經常需要從後端查詢數據到前端頁面展示,當我們的數據很多的時候就可以使用到分頁技術,會使得我們的數據顯示更加美觀合理。
分頁分類
有兩種分頁方式:
- “假分頁”
其實就是採用前端技術對數據進行分頁。當前端頁面請求後臺時將所有符合條件數據全部查詢出來響應給前端,在前端通過一些技術對查詢出來的數據進行分頁。這種方式在數據量較小時效率還行,但是如果當數據量很大時就比較力不從心了,響應會比較慢 - “真分頁”
當前端請求後臺查詢數據時,後臺根據前端傳入的分頁依據使用SQL的分頁查詢查詢對應條數的數據。這種方式就大大的減少了數據量。
分頁實現
當前分頁實現的項目環境是Spring+SpringMVC
爲了便於操作並且不僅僅在一個項目中能夠使用分頁技術,創建一個分頁對象,其中包含的字段如圖中所示。
其中,我們需要從前端傳入的數據有當前頁(如果想隨時更改每一頁的數據顯示數量就還要傳入每頁要顯示的數據條數)。其他的數據:
首頁:恆爲1;
總頁數:根據通過dao層操作數據庫查詢而得到的總數據量/每頁顯示數據量得到
lastPage=totalData%pageSize==0?totalData/pageSize:totalData/pageSize+1
尾頁:等於總頁數
上一頁:這裏需要判斷當前頁是否<=1如果滿足則上一頁爲1,否則上一頁就等於當前頁-1
prePage=currentPage<=1?1:currentPage-1
下一頁:判斷當前頁是否>=總頁數,如果滿足則下一頁=總頁數,否則下一頁=當前頁-1
nextPage=currentPage>=lastPage?totalPage:currentPage+1
大體流程
前端訪問頁面發送請求->被SpringMVC核心DispatcherServlet攔截並且匹配到對應的Controller處理器中進行處理->在處理器中獲取到當前頁(如果是第一次訪問則置當前頁爲1)->通過Service訪問對應的Dao層操作方法->在dao方法中根據傳入的當前頁首先操作數據庫查詢出總數據數並封裝到對象中->我是在分頁實體類的有參構造方法中進行的其他元素的值的計算->分頁對象數據封裝完成之後就可以進行分頁查詢了->使用SQL的分頁查詢語句查詢出符合條件的數據(SELECT * FROM … LIMIT 起始,每頁數據量);其中的起始位置是可以通過 (當前頁-1)*每頁的數據量算出的->將查詢出的數據list封裝到分頁對象中傳遞迴Controller->響應給前端,前端使用jstl+el解析展示
實現
定義分頁對象實體類:
import java.util.List;
public class PageList<T> {
private Integer currentpage = 1; // 當前頁,初始值也爲第一頁
private Integer firstPage = 1;// 首頁爲第一頁
private Integer prePage; // 上一頁
private Integer nextPage; // 下一頁
private Integer lastPage; // 最後一頁
private Integer totalPage; // 總頁數
private Integer totalData; // 總數據
private Integer pageSize; //
private List<T> list; // list集合用來裝查出的數據
public PageList() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "PageList [currentpage=" + currentpage + ", firstPage=" + firstPage + ", prePage=" + prePage
+ ", nextPage=" + nextPage + ", lastPage=" + lastPage + ", totalPage=" + totalPage + ", totalData="
+ totalData + ", pageSize=" + pageSize + ", list=" + list + "]";
}
public Integer getCurrentpage() {
return currentpage;
}
public void setCurrentpage(Integer currentpage) {
this.currentpage = currentpage;
}
public Integer getFirstPage() {
return firstPage;
}
public void setFirstPage(Integer firstPage) {
this.firstPage = firstPage;
}
public Integer getPrePage() {
return prePage;
}
public void setPrePage(Integer prePage) {
this.prePage = prePage;
}
public Integer getNextPage() {
return nextPage;
}
public void setNextPage(Integer nextPage) {
this.nextPage = nextPage;
}
public Integer getLastPage() {
return lastPage;
}
public void setLastPage(Integer lastPage) {
this.lastPage = lastPage;
}
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
public Integer getTotalData() {
return totalData;
}
public void setTotalData(Integer totalData) {
this.totalData = totalData;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
public PageList(Integer currentpage, Integer totalData, Integer pageSize) {
this.currentpage = currentpage;
this.totalData = totalData;
this.pageSize = pageSize;
/**
* 爲頁面中的尾頁、上一頁、下一頁、總頁數賦值
*/
// 總頁數:總數據/每頁數據 。 如果除不盡則向上取整
this.totalPage = this.totalData % this.pageSize == 0 ? this.totalData / this.pageSize
: this.totalData / this.pageSize + 1;
//尾頁:等於總頁數
this.lastPage = this.totalPage;
// 上一頁:如果傳入當前頁頁碼小於等於1則直接賦值爲1
this.prePage = this.currentpage <= 1 ? 1 : this.currentpage - 1;
// 下一頁:如果傳入當前頁頁碼大於等於總頁數則賦值爲總頁數
this.nextPage = this.currentpage >= this.totalPage ? this.totalPage : this.currentpage + 1;
}
}
Controller處理實現:
@Controller
@RequestMapping("/system")
public class CMSController {
@Autowired
private ImageServiceImpl servic;
@RequestMapping("/main")
public String main(Integer currentPage, Integer pageSize, HttpSession session) {
if (currentPage == null) {
currentPage = 1;
}
if(pageSize == null) {
pageSize = 5;
}
PageList<Images> list = servic.queryAll(currentPage,pageSize);
session.setAttribute("page_list", list);
//在SpringMVC中配置了視圖解析器,所以只用返回關鍵字,完整路徑會在視圖解析器中自動拼接
return "main";
}
}
視圖解析器:
<!-- 配置視圖解析器
可以幫助簡化書寫繁瑣路徑的步驟
自動爲我們返回的路徑添加前綴後後綴
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/system/" />
<property name="suffix" value=".jsp" />
</bean>
Service方法:
@Service
public class ImageServiceImpl implements IImageService {
@Autowired
private ImageDaoImpl dao;
@Override
public PageList queryAll(Integer currentPage, Integer pageSize) {
return dao.queryAll(currentPage,pageSize);
}
}
Dao方法:
@Repository
public class ImageDaoImpl implements IImageDao {
@Autowired
private JdbcTemplate jt; //在Spring中自動注入了連接池對象,可以操作數據庫
@Override
public PageList queryAll(Integer currentPage, Integer pageSize) {
/**
* 要根據傳入的當前頁計算出上一頁、下一頁
* 在這裏還要計算出數據總條數,和數據總頁數
*/
//先查詢出總數據條數
String sql = "SELECT COUNT(imgid) FROM images";
Integer totalData = jt.queryForObject(sql, Integer.class);
//封裝到pageList對象中
PageList pageList = new PageList(currentPage,totalData, pageSize);
//查詢分頁數據
sql = "SELECT * FROM images LIMIT ?, ?";
//起始位置= (當前頁-1)*每頁條數
List<Images> list = jt.query(sql, new BeanPropertyRowMapper(Images.class), (currentPage-1)*pageList.getPageSize(), pageList.getPageSize());
pageList.setList(list);
return pageList;
}
}
Spring中爲jt對象注入值:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<!-- 查找當前src下查找jdbc.properties文件 -->
<context:property-placeholder
location="classpath:config/jdbc.properties" />
<bean id="ds"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"
value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 創建JdbcTemplate對象用於jdbc操作 -->
<bean id ="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg name="dataSource" ref="ds"></constructor-arg>
</bean>
<!-- 掃描所有的包,掃描多個包可以使用逗號分隔
Spring負責管理service和dao
-->
<context:component-scan base-package="cn.xer.dao.impl, cn.xer.service.impl" />
</beans>
到這裏,後端的操作基本就完成了,熱騰騰的分頁對象已放入session,隨時可以食用。
前端獲取:
<c:forEach items="${sessionScope.page_list.list}" var="main">
<input type="hidden" id="img_list" value="${sessionScope.img_list }" />
<tr>
<input type="hidden" class="id" value="${main.imgid }" />
<th name="id">${main.imgid }</th>
<th name="img"><img alt="" src="/upload/${main.storename}"
style="width: 100px;"></th>
<th name="storepath">${main.storepath }</th>
<th name="storename">${main.storename }</th>
<th name="intro">${main.intro }</th>
<!-- 判斷是否已啓用 -->
<c:choose>
<c:when test="${main.isenabled == true }">
<th><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></th>
</c:when>
<c:otherwise>
<th><span class="glyphicon glyphicon-remove"
aria-hidden="true"></span></th>
</c:otherwise>
</c:choose>
<th name="date">${main.date }</th>
<th><button class="btn-default tableA edit" style="border-radius:8px;">
<span class="glyphicon glyphicon-pencil" aria-hidden="true">修改</span>
</button> <a href="" class="btn-default tableA"><span
class="glyphicon glyphicon-trash" aria-hidden="true">刪除</span></a></th>
</tr>
</c:forEach>
</table>
<nav class="navbar-right">
<ul class="pagination" id="paging">
<li><span>當前第${sessionScope.page_list.currentpage }頁</span></li>
<li><a
href="${pageContext.request.contextPath}/system/main?currentPage=1">
<span aria-hidden="true">首頁</span>
</a></li>
<li><a
href="${pageContext.request.contextPath}/system/main?currentPage=${sessionScope.page_list.prePage }"
aria-label="上一頁"> <span aria-hidden="true">上一頁</span>
</a></li>
<li></li>
<li><a
href="${pageContext.request.contextPath}/system/main?currentPage=${sessionScope.page_list.nextPage }"
aria-label="下一頁"> <span aria-hidden="true">下一頁</span>
</a></li>
<li><a
href="${pageContext.request.contextPath}/system/main?currentPage=${sessionScope.page_list.lastPage }"
aria-label="尾頁"> <span aria-hidden="true">尾頁</span>
</a></li>
<li><span>總頁數:共${sessionScope.page_list.totalPage }頁</span>
<span>總數據:共${sessionScope.page_list.totalData }條</span></li>
<li><span>每頁顯示:
<select name="pageSize" id="select">
<option value="${sessionScope.page_list.pageSize }">${sessionScope.page_list.pageSize }</option>
<option value="5">5</option>
<option value="8">8</option>
<option value="10">10</option>
</select>
條</span></li>
</ul>
</nav>
在需要展示的地方食用jstl+el就可以獲取到數據了。
當然還有其他方式能過拿到數據,例如,使用ajax請求後臺,在Controller中直接返回一個分頁數據對象的json數據,在前端解析使用即可。具體實現就不展示了。