分页:
分页,是一种将所有数据分段展示的技术,用户每次看到的是通过分页展示的一部分。
通过分页技术的实现,一方面充分利用和学习各种优化工具,并加深对jDBC的理解;另一方面,熟悉web开发的流程。
实现思路流程:
0.准备
0.1)在WEB-INF下新建lib文件夹,导入所需的jar文件,并添加到build path 中。
0.2)在src下编辑c3p0-config.xml文件
1.在util包中写JdbcUtils.java和PageBean.java
2.在entity包中写student.java(用了DbUtils组件,属性与数据库保持一致)①实体类设计
3.在dao包中写接口IStudentDao.java ②数据访问层设计
在dao.impl包中写StudentDao.java
4.在service包中写接口IStudentService.java ③业务逻辑层设计
在service.impl包中写StudentService.java
5.在servlet包中写一个servlet:IndexServlet.java ④servlet控制层开发
6.在WEB-INF下写list.jsp ⑤jsp显示数据
最终的包结构:
事先准备的测试数据库,信息如下:
0.准备
0.1)在WEB-INF下新建lib文件夹,导入所需的jar文件,并添加到build path 中。
0.2)在src下编辑c3p0-config.xml文件
<c3p0-config>
<default-config>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/xiaohua
</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">6</property>
<property name="maxIdleTime">1000</property>
</default-config>
<named-config name="mysql_config">
<property name="jdbcUrl">jdbc:mysql://localhost:3306/xiaohua</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">6</property>
<property name="maxIdleTime">1000</property>
</named-config>
</c3p0-config>
1.在util包中写JdbcUtils.java和PageBean.java
package xiaohua.utils;
import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* @author xiaohua
* 2018-11-12
* 1.初始化c3p0连接池
* 2.创建DbUtils核心工具类对象
*/
public class JdbcUtils {
private static DataSource dataSource;
static {
dataSource=new ComboPooledDataSource();
}
public static QueryRunner getQueryRunner() {
return new QueryRunner(dataSource);
}
}
package xiaohua.utils;
import java.util.List;
//封装分页的参数
public class PageBean <T>{
private int currentPage=1;//当前页,默认显示第一页
private int pageCount=5;//查询返回的行数,默认每页显示5行
private int totalCount;//总记录数
private int totalPage;//总页数
private List<T> pageData;//分页查询到的数据
public PageBean() {
super();
}
//返回总页数
public int getTotalPage() {
if(totalCount%pageCount==0) {
totalPage=totalCount/pageCount;
}else {
totalPage=totalCount/pageCount+1;
}
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public List<T> getPageData() {
return pageData;
}
public void setPageData(List<T> pageData) {
this.pageData = pageData;
}
}
2.在entity包中写student.java(用了DbUtils组件,属性与数据库保持一致)
package xiaohua.entity;
//1.模拟一个实体类:Student
public class Student {
private int id;
private String name;
private int age;
public Student() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
3.在dao包中写接口IStudentDao.java
package xiaohua.dao;
import xiaohua.entity.Student;
import xiaohua.utils.PageBean;
//2.数据访问层设计 之 接口
public interface IStudentDao {
//分页查询数据
public void getAll(PageBean<Student> pb);
//查询总记录数
public int getTotalCount();
}
在dao.impl包中写StudentDao.java
package xiaohua.dao.impl;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import xiaohua.dao.IStudentDao;
import xiaohua.entity.Student;
import xiaohua.utils.JdbcUtils;
import xiaohua.utils.PageBean;
//2.数据访问层 实现
public class StudentDao implements IStudentDao {
@Override
public void getAll(PageBean<Student> pb) {
//将查询到的总记录数,设置到pb对象中
int totalCount =this.getTotalCount();
pb.setTotalCount(totalCount);
/*
* 问题: jsp页面,如果当前页为首页,再点击上一页报错!
* 如果当前页为末页,再点下一页显示有问题!
* 解决:
* 1. 如果当前页 <= 0; 设置当前页为1;
* 2. 如果当前页 > 最大页数; 设置当前页为最大页数
*/
if(pb.getCurrentPage()<=0) {
pb.setCurrentPage(1);
}else if(pb.getCurrentPage()>pb.getTotalPage()) {
pb.setCurrentPage(pb.getTotalPage());
}
//获取当前页,计算当前页的起始行、查询返回的行数
int currentPage=pb.getCurrentPage();
int index=(currentPage-1)*pb.getPageCount();
int count=pb.getPageCount();
//分页查询数据
String sql="SELECT * FROM stu LIMIT ?,?";
try {
QueryRunner qr=JdbcUtils.getQueryRunner();
//查询当前页数据,并设置到pb对象中
List<Student> pageData=qr.query(sql, new BeanListHandler<Student>(Student.class), index,count);
pb.setPageData(pageData);
}catch(Exception e) {
throw new RuntimeException(e);
}
}
@Override
public int getTotalCount() {
//查询总记录数
String sql="SELECT COUNT(*) FROM stu";
try {
QueryRunner qr=JdbcUtils.getQueryRunner();
Long count=qr.query(sql,new ScalarHandler<Long>());
return count.intValue();
}catch(Exception e) {
throw new RuntimeException(e);
}
}
}
4.在service包中写接口IStudentService.java
package xiaohua.service;
import xiaohua.entity.Student;
import xiaohua.utils.PageBean;
//3.业务逻辑层设计之 接口
public interface IStudentService {
//分页查询数据
public void getAll(PageBean<Student> pb);
}
在service.impl包中写StudentService.java
package xiaohua.service.impl;
import xiaohua.dao.IStudentDao;
import xiaohua.dao.impl.StudentDao;
import xiaohua.entity.Student;
import xiaohua.service.IStudentService;
import xiaohua.utils.PageBean;
//3. 业务逻辑层 实现
public class StudentService implements IStudentService{
//创建Dao实例
private IStudentDao studentDao=new StudentDao();
@Override
public void getAll(PageBean<Student> pb) {
try {
studentDao.getAll(pb);
}catch(Exception e) {
throw new RuntimeException(e);
}
}
}
5.在servlet包中写一个servlet:IndexServlet.java
package xiaohua.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import xiaohua.entity.Student;
import xiaohua.service.IStudentService;
import xiaohua.service.impl.StudentService;
import xiaohua.utils.PageBean;
//4.控制层开发
@WebServlet("/IndexServlet")
public class IndexServlet extends HttpServlet {
// 创建Service实例
private IStudentService employeeService = new StudentService();
// 跳转资源
private String uri;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
//1. 获取“当前页”参数; (第一次访问当前页为null)
String currPage = request.getParameter("currentPage");
// 判断
if (currPage == null || "".equals(currPage.trim())){
currPage = "1"; // 第一次访问,设置当前页为1;
}
// 转换
int currentPage = Integer.parseInt(currPage);
//2. 创建PageBean对象,设置当前页参数; 传入service方法参数
PageBean<Student> pageBean = new PageBean<Student>();
pageBean.setCurrentPage(currentPage);
//3. 调用service
employeeService.getAll(pageBean); // 【pageBean已经被dao填充了数据】
//4. 保存pageBean对象,到request域中
request.setAttribute("pageBean", pageBean);
//5. 跳转
uri = "/WEB-INF/list.jsp";
} catch (Exception e) {
//e.printStackTrace(); // 测试使用
uri = "/error/error.jsp";
}
request.getRequestDispatcher(uri).forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
6.在WEB-INF下写list.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!-- 引入jstl核心标签库 -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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>
<table align="center" border="1" width="80%" cellpadding="5" cellspacing="0">
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
</tr>
<!-- 迭代数据 -->
<c:choose>
<c:when test="${not empty requestScope.pageBean.pageData }">
<c:forEach var="stu" items="${requestScope.pageBean.pageData }" varStatus="status" >
<tr>
<td>${status.count }</td>
<td>${stu.name }</td>
<td>${stu.age }</td>
</tr>
</c:forEach>
</c:when>
<c:otherwise>
<tr>
<td>对不起,没有你要找的数据</td>
</tr>
</c:otherwise>
</c:choose>
<tr>
<td colspan="3" align="center">
当前${requestScope.pageBean.currentPage }/${requestScope.pageBean.totalPage }页
<a href="${pageContext.request.contextPath }/IndexServlet?currentPage=1">首页</a>
<a href="${pageContext.request.contextPath }/IndexServlet?currentPage=${requestScope.pageBean.currentPage-1}">上一页</a>
<a href="${pageContext.request.contextPath }/IndexServlet?currentPage=${requestScope.pageBean.currentPage+1}">下一页</a>
<a href="${pageContext.request.contextPath }/IndexServlet?currentPage=${requestScope.pageBean.totalPage}">末页</a>
</td>
</tr>
</table>
</body>
</html>
打开浏览器访问,查看
点下一页,没有问题:
点末页,没有问题
此时再点下一页,可以看到此时 currentPage=6
仍显示末页内容