[TOC]
分頁單獨拿出來講解1
## 步驟 1 : 效果
如圖所示,每頁顯示5條數據。111
注: 沒有分類圖片是正常的,在接下來的知識點就會做增加圖片功能了

## 步驟 2 : Page.java
新增Page這個類專門為分頁提供必要信息
屬性:
`int start; `開始位置
`int count;` 每頁顯示的數量
`int total; `總共有多少條數據
`String param;` 參數(這個屬性在后續有用到,但是分類的分頁查詢里并沒有用到,請忽略)
方法:
`getTotalPage` 根據 每頁顯示的數量count以及總共有多少條數據total,計算出總共有多少頁
`getLast `計算出最后一頁的數值是多少
`isHasPreviouse` 判斷是否有前一頁
`isHasNext` 判斷是否有后一頁
~~~
package com.dodoke.tmall.util;
/**
* 分頁類
* @author cui
*
*/
public class Page {
/**
* 開始頁數
*/
private int start;
/**
* 每頁顯示個數
*/
private int count;
/**
* 總個數
*/
private int total;
/**
* 參數
*/
private String param;
/**
* 默認每頁顯示5條
*/
private static final int defaultCount = 5;
public Page() {
count = defaultCount;
}
public Page(int start, int count) {
this();
this.start = start;
this.count = count;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
/**
* 判斷是否有前一頁
* @return boolean
*/
public boolean isHasPreviouse() {
if (start == 0) {
return false;
}
return true;
}
/**
* 判斷是否有后一頁
* @return boolean
*/
public boolean isHasNext() {
if (start == getLast()){
return false;
}
return true;
}
/**
* 計算出最后一頁的數值是多少
* @return int
*/
public int getLast() {
int last;
// 假設總數是50,是能夠被5整除的,那么最后一頁的開始就是45
if (0 == total % count)
last = total - count;
// 假設總數是51,不能夠被5整除的,那么最后一頁的開始就是50
else
last = total - total % count;
last = last < 0 ? 0 : last;
return last;
}
/**
* 根據 每頁顯示的數量count以及總共有多少條數據total,計算出總共有多少頁
* @return int
*/
public int getTotalPage() {
int totalPage;
// 假設總數是50,是能夠被5整除的,那么就有10頁
if (0 == total % count) {
totalPage = total / count;
}
// 假設總數是51,不能夠被5整除的,那么就有11頁
else {
totalPage = total / count + 1;
}
if (0 == totalPage) {
totalPage = 1;
}
return totalPage;
}
@Override
public String toString() {
return "Page [start=" + start + ", count=" + count + ", total=" + total + ", getStart()=" + getStart()
+ ", getCount()=" + getCount() + ", isHasPreviouse()=" + isHasPreviouse() + ", isHasNext()="
+ isHasNext() + ", getTotalPage()=" + getTotalPage() + ", getLast()=" + getLast() + "]";
}
}
~~~
## 步驟 3 : CategoryMapper.xml
修改CategoryMapper.xml,以提供帶分頁的查詢語句和獲取總數的sql語句
~~~
<?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.dodoke.tmall.mapper.CategoryMapper">
<select id="list" resultType="Category">
select * from t_category order by id desc
<if test="start!=null and count!=null">
limit #{start},#{count}
</if>
</select>
<select id="total" resultType="int">
select count(*) from t_category
</select>
</mapper>
~~~
## 步驟 4 : CategoryMapper
修改CategoryMapper,提供一個支持分頁的查詢方法`list(Page page)`和獲取總數的方法total
~~~
package com.dodoke.tmall.mapper;
import java.util.List;
import com.dodoke.tmall.pojo.Category;
import com.dodoke.tmall.util.Page;
public interface CategoryMapper {
List<Category> list(Page page);
public int total();
}
~~~
## 步驟 5 : CategoryService
修改CategoryService,提供一個支持分頁的查詢方法`list(Page page)`和獲取總數的方法total
~~~
package com.dodoke.tmall.service;
import java.util.List;
import com.dodoke.tmall.pojo.Category;
import com.dodoke.tmall.util.Page;
public interface CategoryService {
List<Category> list(Page page);
int total();
}
~~~
## 步驟 6 : CategoryServiceImpl
修改CategoryServiceImpl,提供一個支持分頁的查詢方法`list(Page page)`和獲取總數的方法total。
~~~
package com.dodoke.tmall.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.dodoke.tmall.mapper.CategoryMapper;
import com.dodoke.tmall.pojo.Category;
import com.dodoke.tmall.service.CategoryService;
import com.dodoke.tmall.util.Page;
@Service
public class CategoryServiceImpl implements CategoryService {
@Autowired
CategoryMapper categoryMapper;
@Override
public List<Category> list(Page page) {
return categoryMapper.list(page);
}
@Override
public int total() {
return categoryMapper.total();
}
}
~~~
## 步驟 7 : CategoryController
修改CategoryController
1. 為方法list增加參數Page,用于獲取瀏覽器傳遞過來的分頁信息
2. `categoryService.list(page)`; 獲取當前頁的分類集合
3. 通過`categoryService.total()`; 獲取分類總數
4. 通過`page.setTotal(total)`; 為分頁對象設置總數
5. 把分類集合放在"cs"中
6. 把分頁對象放在 "page“ 中
7. 跳轉到listCategory.jsp頁面
~~~
package com.dodoke.tmall.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.dodoke.tmall.pojo.Category;
import com.dodoke.tmall.service.CategoryService;
import com.dodoke.tmall.util.Page;
@RequestMapping("")
@Controller
public class CategoryController {
@Autowired
CategoryService categoryService;
@RequestMapping("admin_category_list")
public String list(Model model,Page page) {
List<Category> cs = categoryService.list(page);
int total = categoryService.total();
page.setTotal(total);
model.addAttribute("cs", cs);
model.addAttribute("page",page);
return "admin/listCategory";
}
}
~~~
> 1. start會被自動封裝到page里的
> 2. page 對象 最開始訪問方法`list(Model model,Page page)`時 ,實際上page就是相當于你`new page()`的默認值,參數如下:
```
private int start; //開始頁數
private int count; //每頁顯示個數
private int total; //總個數
private String param; //參數
private static final int defaultCount = 5; //默認每頁顯示5條
```
相當于最開始時` start =0;count=5;total =0;param=null;`
所以第一次查詢就查的是0至5的數據,后面通過前臺頁面點擊在此過來start 就會再次改變
## 步驟 8 : listCategory.jsp
本來注釋掉的43行,去掉注釋,即
`<%@include file="../include/admin/adminPage.jsp" %>`
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@include file="../include/admin/adminHeader.jsp"%>
<%@include file="../include/admin/adminNavigator.jsp"%>
<title>分類管理</title>
<div class="workingArea">
<h1 class="label label-info" >分類管理</h1>
<br>
<br>
<div class="listDataTableDiv">
<table class="table table-striped table-bordered table-hover table-condensed">
<thead>
<tr class="success">
<th>ID</th>
<th>圖片</th>
<th>分類名稱</th>
<th>屬性管理</th>
<th>產品管理</th>
<th>編輯</th>
<th>刪除</th>
</tr>
</thead>
<tbody>
<c:forEach items="${cs}" var="c">
<tr>
<td>${c.id}</td>
<td><img height="40px" src="img/category/${c.id}.jpg"></td>
<td>${c.name}</td>
<td><a href="admin_property_list?cid=${c.id}"><span class="glyphicon glyphicon-th-list"></span></a></td>
<td><a href="admin_product_list?cid=${c.id}"><span class="glyphicon glyphicon-shopping-cart"></span></a></td>
<td><a href="admin_category_edit?id=${c.id}"><span class="glyphicon glyphicon-edit"></span></a></td>
<td><a deleteLink="true" href="admin_category_delete?id=${c.id}"><span class=" glyphicon glyphicon-trash"></span></a></td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
<div class="pageDiv">
<%@include file="../include/admin/adminPage.jsp" %>
</div>
<div class="panel panel-warning addDiv">
<div class="panel-heading">新增分類</div>
<div class="panel-body">
<form method="post" id="addForm" action="admin_category_add" enctype="multipart/form-data">
<table class="addTable">
<tr>
<td>分類名稱</td>
<td><input id="name" name="name" type="text" class="form-control"></td>
</tr>
<tr>
<td>分類圖片</td>
<td>
<input id="categoryPic" accept="image/*" type="file" name="image" />
</td>
</tr>
<tr class="submitTR">
<td colspan="2" align="center">
<button type="submit" class="btn btn-success">提 交</button>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
<%@include file="../include/admin/adminFooter.jsp"%>
<script>
$(function(){
$("#addForm").submit(function(){
if(!checkEmpty("name","分類名稱"))
return false;
if(!checkEmpty("categoryPic","分類圖片"))
return false;
return true;
});
});
</script>
~~~
## 步驟 9 : 為了便于理解,先來一個簡化了的adminPage.jsp
在listCategory.jsp頁面包含了分頁專用`jsp:adminPage.jsp`
在其中,依據page對象,進行分頁超鏈元素的顯示
**完整版的adminPage.jsp** 比較復雜,為了便于大家理解,我先把完整版的adminPage.jsp簡化一下
首先,分頁超鏈的效果,用的**Bootstrap的分頁**效果來制作
首頁超鏈:
~~~
<li>
<a href="?start=0" >
<span aria-hidden="true">?</span>
</a>
</li>
~~~
上一頁超鏈:
~~~
<li >
<a href="?start=${page.start-page.count}" >
<span aria-hidden="true">?</span>
</a>
</li>
~~~
下一頁超鏈:
~~~
<li >
<a href="?start=${page.start+page.count}">
<span aria-hidden="true">?</span>
</a>
</li>
~~~
最后一頁
~~~
<li >
<a href="?start=${page.last}">
<span aria-hidden="true">?</span>
</a>
</li>
~~~
中間頁
~~~
<c:forEach begin="0" end="${page.totalPage-1}" varStatus="status">
<li>
<a href="?start=${status.index*page.count}" class="current">${status.count}</a>
</li>
</c:forEach>
~~~
> 直接寫問號就會導致再度訪問當前頁面。 所以這樣寫就可以在不同的頁面都適用,即分類管理分頁也可以用,產品管理分頁也可以用。
## 步驟 10 : 完整版的adminPage.jsp
簡化的adminPage.jsp 用于幫助大家理解,其存在的問題是,即便是沒有下一頁的數據了,下一頁超鏈也可以點擊,點出來的頁面是空白的。(首頁,上一頁,下一頁和最后一頁都存在這個問題)
那么所謂的完整版的adminPage.jsp,就是對這些邊界進行了處理。當沒有下一頁的時候,對應超鏈處于不可點擊狀態。
比如首頁:
當page.hasPreviouse為false的時候,為首頁連接套用Bootstrap樣式 disabled
~~~
<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?page.start=0${page.param}">
<span aria-hidden="true">«</span>
</a>
</li>
~~~
> 注: `hasPreviouse`會的導致`isHasPreviouse()`方法被調用,即如果屬性是boolean類型,那么就會自動調用`isXXX`方法了
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<nav>
<ul class="pagination">
<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?start=0${page.param}" >
<span aria-hidden="true">?</span>
</a>
</li>
<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?start=${page.start-page.count}${page.param}">
<span aria-hidden="true">?</span>
</a>
</li>
<c:forEach begin="0" end="${page.totalPage-1}" varStatus="status">
<li <c:if test="${status.index*page.count==page.start}">class="disabled"</c:if>>
<a
href="?start=${status.index*page.count}${page.param}"
<c:if test="${status.index*page.count==page.start}">class="current"</c:if>
>${status.count}</a>
</li>
</c:forEach>
<li <c:if test="${!page.hasNext}">class="disabled"</c:if>>
<a href="?start=${page.start+page.count}${page.param}">
<span aria-hidden="true">?</span>
</a>
</li>
<li <c:if test="${!page.hasNext}">class="disabled"</c:if>>
<a href="?start=${page.last}${page.param}">
<span aria-hidden="true">?</span>
</a>
</li>
</ul>
</nav>
<script>
$(function(){
$("ul.pagination li.disabled a").click(function(){
return false;
});
});
</script>
~~~
## 步驟 11 : 自己做一遍
拿到本章節對應tmall_ssm.rar, 在其基礎之上,按照當前的步驟,自己做一遍,把效果做出來,理解和消化各個步驟的內容,轉化為自己的技能。
- 項目簡介
- 功能一覽
- 前臺
- 后臺
- 開發流程
- 需求分析-展示
- 首頁
- 產品頁
- 分類頁
- 搜索結果頁
- 購物車查看頁
- 結算頁
- 確認支付頁
- 支付成功頁
- 我的訂單頁
- 確認收貨頁
- 確認收貨成功頁
- 評價頁
- 需求分析-交互
- 分類頁排序
- 立即購買
- 加入購物車
- 調整訂單項數量
- 刪除訂單項
- 生成訂單
- 訂單頁功能
- 確認付款
- 確認收貨
- 提交評價信息
- 登錄
- 注冊
- 退出
- 搜索
- 前臺需求列表
- 需求分析后臺
- 分類管理
- 屬性管理
- 產品管理
- 產品圖片管理
- 產品屬性設置
- 用戶管理
- 訂單管理
- 后臺需求列表
- 表結構設計
- 數據建模
- 表與表之間的關系
- 后臺-分類管理
- 可運行的項目
- 靜態資源
- JSP包含關系
- 查詢
- 分頁
- 增加
- 刪除
- 編輯
- 修改
- 做一遍
- 重構
- 分頁方式
- 分類逆向工程
- 所有逆向工程
- 后臺其他頁面
- 屬性管理實現
- 產品管理實現
- 產品圖片管理實現
- 產品屬性值設置
- 用戶管理實現
- 訂單管理實現
- 前端
- 前臺-首頁
- 可運行的項目
- 靜態資源
- ForeController
- home方法
- home.jsp
- homePage.jsp
- 前臺-無需登錄
- 注冊
- 登錄
- 退出
- 產品頁
- 模態登錄
- 分類頁
- 搜索
- 前臺-需要登錄
- 購物流程
- 立即購買
- 結算頁面
- 加入購物車
- 查看購物車頁面
- 登錄狀態攔截器
- 其他攔截器
- 購物車頁面操作
- 訂單狀態圖
- 生成訂單
- 我的訂單頁
- 我的訂單頁操作
- 評價產品
- 總結