一、分页的原理
第N页/共M页 首页 上一页 1 2 3 4 5 6 7 8 9 10 下一页 尾页
分页的优点:只查询一页,不用查询所有页!
二、分页数据
页面的数据都是由Servlet传递来的!
Servlet:
- 当前面:pageCode,pc;pc:如果页面没有传递当前页码,那么Servlet默认是第一页,或者按页面传递的来准!
- 总页数:totalPages,tp;tp:总记录数/每页记录数
- 总记录数:totalRecored,tr;tr:dao来获取,select count(*) from t_customer;
- 每页记录数:业务数据或叫系统数据!10行!
- 当前页数据:beanList
-
url
三、分页Bean的设计
这些分页数据总要在各层之间来回的传递!
我们把这些分页数据封装到一个javabean中,它就叫分页Bean,例如:PageBean
PageBean.java
package waf.yty.cstm.domain;
import java.util.List;
public class PageBean<T> {
private int pc; //当前页码 page code
// private int tp; //总页数 total page
private int tr; //总记录 total record
private int ps; //每页记录数 page size
private List<T> beanList; //当前页的记录
private String url; //它就是url后的条件!
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getPc() {
return pc;
}
public void setPc(int pc) {
this.pc = pc;
}
/**
* 计算总页数
* @return
*/
public int getTp() {
// 通过总记录和每页记录数来计算总页数
int tp = tr / ps;
return tr%ps==0 ? tp : tp+1;
}
// public void setTp(int tp) {
// this.tp = tp;
// }
public int getTr() {
return tr;
}
public void setTr(int tr) {
this.tr = tr;
}
public int getPs() {
return ps;
}
public void setPs(int ps) {
this.ps = ps;
}
public List<T> getBeanList() {
return beanList;
}
public void setBeanList(List<T> beanList) {
this.beanList = beanList;
}
}
四、分页在各层中的处理
五、显示分页页码列表
- 最多显示多少个页码!定为10
- 当前页,在页码列表中的位置,定为6
- 只需要当前页码来定出来页码列表!
- 定下来页码列表只需要两样数据:begin 和 end
- 需要使用pc来推算出begin和end
- begin = pc – 5
- end = pc + 4
计算公式:
如果总页数<=10(列表长度),那么begin=1,end=总页数
使用公式计算;begin=pc-5, end=pc + 4
头溢出:当begin<1时,让begin=1
尾溢出:当end>${tp}时,让end=${tp}
六、在超链接中要保留参数
当使用多条件查询后,然后在点击第2 页时,这个第2页超链接没有条件了,所以会丢失条件,所以我们需要在页面上的所有链接都要保留条件!我们要把条件以一个字符串的形式保存到PageBean的url中!这个任务交给Servlet!
七、加入分页功能后代码的一些改动
7.1、CustomerServlet.java
package waf.yty.cstm.web.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sound.sampled.AudioFormat.Encoding;
import cn.itcast.commons.CommonUtils;
import cn.itcast.servlet.BaseServlet;
import waf.yty.cstm.domain.Customer;
import waf.yty.cstm.domain.PageBean;
import waf.yty.cstm.service.CustomerService;
/**
* Web层
* @author yangtengyu
*
*/
public class CustomerServlet extends BaseServlet {
private CustomerService customerService = new CustomerService();
public String add(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.封装表单数据到Customer对象
Customer c = CommonUtils.toBean(request.getParameterMap(), Customer.class);
// 2.cid,uuid
c.setCid(CommonUtils.uuid());
// 3.添加工作
customerService.add(c);
// 4.request域保存成功信息
request.setAttribute("msg", "恭喜,添加客户成功!");
// 5.转发到msg.jsp
return "f:/msg.jsp";
}
/**
* 查询所有
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
// public String findAll(HttpServletRequest request, HttpServletResponse response)
// throws ServletException, IOException {
//
// 1.调用service得到所有客户
// 2.保存到request域
request.setAttribute("cstmList", customerService.findAll());
// 3.转发到list.jsp
return "f:/list.jsp";
//
// }
public String findAll(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.获取页面传递的pc
int pc = getPc(request);
// 2.给定ps的值
int ps = 10;
// 3.使用pc和ps调用service方法,得到pageBean,保存request域
PageBean<Customer> pb = customerService.findAll(pc,ps);
// 设置url
pb.setUrl(getUrl(request));
request.setAttribute("pb", pb);
// 4.转发list.jsp
return "/list.jsp";
}
private int getPc(HttpServletRequest request) {
String value = request.getParameter("pc");
if (value == null || value.trim().isEmpty()) {
return 1;
}
return Integer.parseInt(value);
}
/**
* 编辑之前的加载工作
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
public String preEdit(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.获取cid
String cid = request.getParameter("cid");
// 2.使用cid调用service方法,得到customer对象
Customer cstm = customerService.load(cid);
// 3.把customer保存到request域中
request.setAttribute("cstm", cstm);
// 4.转发edit.jsp显示表单
return "f:/edit.jsp";
}
public String edit(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.封装表单数据到Customer对象中
Customer c = CommonUtils.toBean(request.getParameterMap(), Customer.class);
// 2.调用service方法完成修改
customerService.edit(c);
// 3.保存成功信息request域
request.setAttribute("msg", "修改客户成功!");
// 4.转发到msg.jsp
return "f:/msg.jsp";
}
public String delete(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.获取要删除的cid
String cid = request.getParameter("cid");
// 2.调用service的delete方法
customerService.delete(cid);
// 3.保存删除成功次信息
request.setAttribute("msg", "删除客户成功!");
// 4.请求转发
return "f:/msg.jsp";
}
// public String query(HttpServletRequest request, HttpServletResponse response)
// throws ServletException, IOException {
//
// Customer condition = CommonUtils.toBean(request.getParameterMap(), Customer.class);
// List<Customer> cstmList = customerService.query(condition);
// request.setAttribute("cstmList", cstmList);
// return "/list.jsp";
// }
public String query(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// System.out.println(getUrl(request));
Customer condition = CommonUtils.toBean(request.getParameterMap(), Customer.class);
// 0.处理GET请求方式编码问题!
// condition = encoding(condition);
// 1.获取页面传递的pc
int pc = getPc(request);
// 2.给定ps的值
int ps = 10;
PageBean<Customer> pb = customerService.query(condition,pc,ps);
// 得到url,保存到pb中
pb.setUrl(getUrl(request));
request.setAttribute("pb", pb);
return "/list.jsp";
}
private String getUrl(HttpServletRequest request) {
String contextPath = request.getContextPath();
String servletPath = request.getServletPath();
String queryString = request.getQueryString();
if (queryString.contains("&pc=")) {
int index = queryString.lastIndexOf("&pc=");
queryString = queryString.substring(0, index);
}
return contextPath + servletPath + "?" + queryString;
}
}
7.2、CustomerDao.java
package waf.yty.cstm.dao;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.text.DefaultEditorKit.CutAction;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import cn.itcast.jdbc.TxQueryRunner;
import waf.yty.cstm.domain.Customer;
import waf.yty.cstm.domain.PageBean;
public class CustomerDao {
private QueryRunner qr = new TxQueryRunner();
/**
* 添加客户
* @param c
*/
public void add(Customer c) {
try {
String sql = "insert into t_customer values (?,?,?,?,?,?,?)";
Object[] params = {c.getCid(),c.getCname(),c.getGender(),
c.getBirthday(),c.getCellphone(),c.getEmail(),c.getDescription()};
qr.update(sql,params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 查询所有
* @return
*/
public PageBean<Customer> findAll(int pc, int ps) {
try {
// 1.得到pb,设置pc和ps
PageBean<Customer> pb = new PageBean<Customer>();
pb.setPc(pc);
pb.setPs(ps);
// 2.设置tr
String sql = "select count(*) from t_customer";
Number num = (Number) qr.query(sql, new ScalarHandler());
int tr = num.intValue();
pb.setTr(tr);
// 3.得到beanList
sql = "select * from t_customer order by cname limit ?,?";
List<Customer> beanList = qr.query(sql,
new BeanListHandler<Customer>(Customer.class),
(pc-1)*ps,ps);
pb.setBeanList(beanList);
return pb;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 加载要修改的客户
* @param cid
* @return
*/
public Customer load(String cid) {
try {
String sql = "select * from t_customer where cid=?";
return qr.query(sql, new BeanHandler<Customer>(Customer.class), cid);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 修改单体客户
* @param c
*/
public void edit(Customer c) {
try {
String sql = "update t_customer set cname=?, gender=?, birthday=?," +
"cellphone=?, email=?, description=? where cid=?;";
Object[] params = {c.getCname(),c.getGender(),c.getBirthday(),
c.getCellphone(),c.getEmail(),c.getDescription(),c.getCid()};
int result = qr.update(sql, params);
System.out.println(result);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 删除某位客户
* @param cid
*/
public void delete(String cid) {
try {
String sql = "delete from t_customer where cid=?";
qr.update(sql,cid);
// if (deleteResult != 0) {
//
// }
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public PageBean<Customer> query(Customer condition, int pc, int ps) {
try {
// 1.创建PageBean对象并设置pc和ps属性
PageBean<Customer> pb = new PageBean<Customer>();
pb.setPc(pc);
pb.setPs(ps);
// 2.得到tr
// 2.1 给出sql前半句
StringBuilder cntSql = new StringBuilder("select count(*) from t_customer ");
StringBuilder whereSql = new StringBuilder("where 1=1 ");
List<Object> params = new ArrayList<Object>();
// 2.2 判断条件,向sql中追加where子句
String cname = condition.getCname();
if (cname != null && !cname.trim().isEmpty()) {
whereSql.append(" and cname like ?");
params.add("%" + cname + "%");
}
String gender = condition.getGender();
if (gender != null && !gender.trim().isEmpty()) {
whereSql.append(" and gender=?");
params.add(gender);
}
String cellphone = condition.getCellphone();
if (cellphone != null && !cellphone.trim().isEmpty()) {
whereSql.append(" and cellphone like ?");
params.add("%" + cellphone + "%");
}
String email = condition.getEmail();
if (email != null && !email.trim().isEmpty()) {
whereSql.append(" and email like ? ");
params.add("%" + email + "%");
}
Number num = (Number) qr.query(cntSql.append(whereSql).toString(),
new ScalarHandler(),params.toArray());
int tr = num.intValue();
pb.setTr(tr);
// 3.得到beanList
StringBuilder sql = new StringBuilder("select * from t_customer ");
// 3.1给出limit子句
StringBuilder limitSql = new StringBuilder(" limit ?,? ");
params.add((pc-1)*ps);
params.add(ps);
List<Customer> beanList = qr.query(sql.append(whereSql).append(limitSql).toString(),
new BeanListHandler<Customer>(Customer.class),
params.toArray());
pb.setBeanList(beanList);
return pb;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
7.3、query.jsp
将表单提交的方法改为method="get"。
因为转发到分页后的list.jsp页面时,我们点击页数查询时都为超链接get请求,所用不用原来的post请求方式。
7.4、list.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>客户列表</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<h3 align="center">客户列表</h3>
<table border="1" width="70%" align="center">
<tr>
<th>客户姓名</th>
<th>性别</th>
<th>生日</th>
<th>手机</th>
<th>邮箱</th>
<th>描述</th>
<th>操作</th>
</tr>
<c:forEach items="${pb.beanList}" var="cstm">
<tr>
<%-- <td>${cstm.cid} </td> --%>
<td>${cstm.cname} </td>
<td>${cstm.gender}</td>
<td>${cstm.birthday}</td>
<td>${cstm.cellphone}</td>
<td>${cstm.email}</td>
<td>${cstm.description}</td>
<!-- <td>萨弗隆尖塔</td> -->
<td>
<a href="<c:url value='/CustomerServlet?method=preEdit&cid=${cstm.cid }'/>">编辑</a>
<a href="<c:url value='/CustomerServlet?method=delete&cid=${cstm.cid }'/>">删除</a>
</td>
</tr>
</c:forEach>
</table>
<br/>
<%--
给出分页的链接
--%>
<center>
第${pb.pc}页/共${pb.tp}页
<a href="${pb.url }&pc=1">首页</a>
<c:if test="${pb.pc > 1}">
<a href="${pb.url }&pc=${pb.pc-1}">上一页</a>
</c:if>
<%-- 计算begin、end --%>
<c:choose>
<%-- 如果总页数不足10页,那么现实所有页数 --%>
<c:when test="${pb.tp <= 10 }">
<c:set var="begin" value="1"/>
<c:set var="end" value="${pb.tp}"/>
</c:when>
<%-- 总页数>10时,通过公式计算出begin和end --%>
<c:otherwise>
<c:set var="begin" value="${pb.pc-5 }"/>
<c:set var="end" value="${pb.pc+4}"/>
<%-- 头溢出 --%>
<c:if test="${begin < 1 }">
<c:set var="begin" value="1"/>
<c:set var="end" value="10"/>
</c:if>
<%-- 尾溢出 --%>
<c:if test="${end > pb.tp }">
<c:set var="begin" value="${pb.tp - 9 }"/>
<c:set var="end" value="${pb.tp }"/>
</c:if>
</c:otherwise>
</c:choose>
<%-- 循环遍历页码列表 --%>
<c:forEach var="i" begin="${begin }" end="${end }">
<c:choose>
<c:when test="${i eq pb.pc }">
[${i}]
</c:when>
<c:otherwise>
<a href="${pb.url }&pc=${i}">[${i}]</a>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${pb.pc < pb.tp}">
<a href="${pb.url }&pc=${pb.pc+1}">下一页</a>
</c:if>
<a href="${pb.url }&pc=${pb.tp}">尾页</a>
</center>
</body>
</html>