[TOC]
> 分页单独拿出来讲解
# 步骤 1 : 效果
如图所示,每页显示5条数据
注: 没有分类图片是正常的,在接下来的知识点就会做增加图片功能了
![](https://box.kancloud.cn/8ac4d1288627df3e2e0d2c25c4b4ba9f_1892x432.png)
# 步骤 2 : Page.java
新增Page这个类专门为分页提供必要信息
属性:
`int start; `开始位置
`int count;` 每页显示的数量
`int total; `总共有多少条数据
`String param;` 参数(这个属性在后续有用到,但是分类的分页查询里并没有用到,请忽略)
方法:
`getTotalPage` 根据 每页显示的数量count以及总共有多少条数据total,计算出总共有多少页
`getLast `计算出最后一页的数值是多少
`isHasPreviouse` 判断是否有前一页
`isHasNext` 判断是否有后一页
```
package com.dodoke.util;
public class Page {
private int start;
private int count;
private int total;
private String param;
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 Page(int start, int count) {
super();
this.start = start;
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;
}
public boolean isHasPreviouse() {
if (start == 0)
return false;
return true;
}
public boolean isHasNext() {
if (start == getLast())
return false;
return true;
}
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;
}
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;
}
}
```
# 步骤 3 : 获取分页参数
获取分页信息是在BaseBackServlet的service方法中
```
int start = 0;
int count = 5;
String startTmp = request.getParameter("page.start");
String countTmp = request.getParameter("page.count");
if (null != startTmp) {
start = Integer.parseInt(startTmp);
}
if (null != countTmp) {
count = Integer.parseInt(countTmp);
}
Page page = new Page(start, count);
```
获取网页上传递来的开始位置,以及每页需要显示的数量
如果传递数据过来,开始位置取0,每页显示的数量取默认值:5.
```
package com.dodoke.controller;
import java.lang.reflect.Method;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.dodoke.dao.impl.CategoryDaoImpl;
import com.dodoke.dao.inter.CategoryDao;
import com.dodoke.util.Page;
/**
* Servlet implementation class BaseBackServlet
*/
@WebServlet("/BaseBackServlet")
public abstract class BaseBackServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public abstract String add(HttpServletRequest request, HttpServletResponse response);
public abstract String delete(HttpServletRequest request, HttpServletResponse response);
public abstract String edit(HttpServletRequest request, HttpServletResponse response);
public abstract String update(HttpServletRequest request, HttpServletResponse response);
public abstract String list(HttpServletRequest request, HttpServletResponse response, Page page);
public CategoryDao categoryDao = new CategoryDaoImpl();
public void service(HttpServletRequest request, HttpServletResponse response) {
int start = 0;
int count = 5;
String startTmp = request.getParameter("page.start");
String countTmp = request.getParameter("page.count");
if (null != startTmp) {
start = Integer.parseInt(startTmp);
}
if (null != countTmp) {
count = Integer.parseInt(countTmp);
}
Page page = new Page(start, count);
try {
/* 借助反射,调用对应的方法 */
String method = (String) request.getAttribute("method");
Method m;
String redirect;
if ("list".equals(method)) {
m = this.getClass().getMethod(method, javax.servlet.http.HttpServletRequest.class,
javax.servlet.http.HttpServletResponse.class,Page.class);
redirect = m.invoke(this, request, response, page).toString();
} else {
m = this.getClass().getMethod(method, javax.servlet.http.HttpServletRequest.class,
javax.servlet.http.HttpServletResponse.class);
redirect = m.invoke(this, request, response).toString();
}
/* 根据方法的返回值,进行相应的客户端跳转,服务端跳转,或者仅仅是输出字符串 */
System.out.println(redirect);
if (redirect.startsWith("@")) {
response.sendRedirect(redirect.substring(1));
} else if (redirect.startsWith("%")) {
response.getWriter().print(redirect.substring(1));
} else {
request.getRequestDispatcher(redirect).forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
```
# 步骤 4 : 基于分页参数,获取数据
接着就通过反射,访问了CategoryServlet的list()方法,并在其中通过categoryDAO,基于page的start,和count值,获取分页数据。
```
List<Category> cs = categoryDao.list(page.getStart(),page.getCount());
```
# 步骤 5 : 为page对象设置总数
除此之外,还为page对象添加了总数
```
int total = categoryDao.getTotal();
page.setTotal(total);
```
为什么要加这个总数? 因为在分页显示的时候,要依据这个总数来判断一共有多少页面,最后一页是多少。
接着通过
```
request.setAttribute("page", page);
```
把page对象,传参到了listCategory.jsp页面
# 步骤 6 : 为了便于理解,先来一个简化了的adminPage.jsp
在listCategory.jsp页面包含了分页专用jsp:adminPage.jsp
在其中,依据page对象,进行分页超链元素的显示
完整版的adminPage.jsp 比较复杂,为了便于大家理解,我先把完整版的adminPage.jsp简化一下
首先,分页超链的效果,用的Bootstrap的分页效果来制作
首页超链:
```
<li>
<a href="?page.start=0" aria-label="Previous" >
<span aria-hidden="true">«</span>
</a>
</li>
```
上一页超链:
```
<li >
<a href="?page.start=${page.start-page.count}" aria-label="Previous" >
<span aria-hidden="true">‹</span>
</a>
</li>
```
下一页超链:
```
<li >
<a href="?page.start=${page.start+page.count}" aria-label="Next">
<span aria-hidden="true">›</span>
</a>
</li>
```
最后一页
```
<li >
<a href="?page.start=${page.last}" aria-label="Next">
<span aria-hidden="true">»</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>
```
```
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<script>
$(function(){
$("ul.pagination li.disabled a").click(function(){
return false;
});
});
</script>
<nav>
<ul class="pagination">
<li>
<a href="?page.start=0" aria-label="Previous" >
<span aria-hidden="true">«</span>
</a>
</li>
<li >
<a href="?page.start=${page.start-page.count}" aria-label="Previous" >
<span aria-hidden="true">‹</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}" aria-label="Next">
<span aria-hidden="true">›</span>
</a>
</li>
<li >
<a href="?page.start=${page.last}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
```
# 步骤 7 : 完整版的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}" aria-label="Previous" >
<span aria-hidden="true">«</span>
</a>
</li>
```
![](https://box.kancloud.cn/756e933d2fcde8996e418619fed2453e_194x62.png)
```
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<script>
$(function(){
$("ul.pagination li.disabled a").click(function(){
return false;
});
});
</script>
<nav>
<ul class="pagination">
<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?page.start=0${page.param}" aria-label="Previous" >
<span aria-hidden="true">«</span>
</a>
</li>
<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?page.start=${page.start-page.count}${page.param}" aria-label="Previous" >
<span aria-hidden="true">‹</span>
</a>
</li>
<c:forEach begin="0" end="${page.totalPage-1}" varStatus="status">
<c:if test="${status.count*page.count-page.start<=20 && status.count*page.count-page.start>=-10}">
<li <c:if test="${status.index*page.count==page.start}">class="disabled"</c:if>>
<a
href="?page.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:if>
</c:forEach>
<li <c:if test="${!page.hasNext}">class="disabled"</c:if>>
<a href="?page.start=${page.start+page.count}${page.param}" aria-label="Next">
<span aria-hidden="true">›</span>
</a>
</li>
<li <c:if test="${!page.hasNext}">class="disabled"</c:if>>
<a href="?page.start=${page.last}${page.param}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
```
- 项目简介
- 功能一览
- 前台
- 后台
- 开发流程
- 需求分析-展示
- 首页
- 产品页
- 分类页
- 搜索结果页
- 购物车查看页
- 结算页
- 确认支付页
- 支付成功页
- 我的订单页
- 确认收货页
- 评价页
- 页头信息展示
- 需求分析-交互
- 分类页排序
- 立即购买
- 加入购物车
- 调整订单项数量
- 删除订单项
- 生成订单
- 订单页功能
- 确认付款
- 确认收货
- 提交评价信息
- 登录
- 注册
- 退出
- 搜索
- 前台需求列表
- 需求分析后台
- 分类管理
- 属性管理
- 产品管理
- 产品图片管理
- 产品属性设置
- 用户管理
- 订单管理
- 后台需求列表
- 表结构设计
- 数据建模
- 表与表之间的关系
- 实体类设计
- DAO类设计
- 工具类
- CategoryDao设计
- Service业务类设计
- 后台-分类管理
- 可运行的项目
- 静态资源
- FILTER配合SERVLET
- JSP包含关系
- 查询
- 分页
- 增加
- 删除
- 编辑
- 修改
- 后台其他管理
- 属性管理
- 产品管理
- 产品图片管理
- 产品属性值设置
- 用户管理
- 订单管理