前段时间学习SSH框架用到分页知识,为此还回顾了一下之前JavaWeb中的分页技术
首先我们先创建一个库和表用来展示分页结果
create table Employee(
empId int(11) NOT NULL AUTO_INCREMENT primary key,
empName varchar(20) NOT NULL,
dept_id int(20) NOT NULL
);
insert into Employee(empName,dept_id) values('aa',1);
接下来我用c3p0连接池来连接数据库
首先我们准备c3p0-config.xml的配置(在ComboPooledDataSource()初始c3p0连接池会加载这里面的配置信息,连接具体的数据库对象)
<c3p0-config>
<default-config>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo
</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">6</property>
<property name="maxIdleTime">1000</property>
</default-config>
接下来写一个连接数据库的工具类,完成
1.初始化数据库
2.创建DbUtils核心工具类对象QueryRunner
package cn.itcast.utils;
import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* 工具类
* 1. 初始化C3P0连接池
* 2. 创建DbUtils核心工具类对象
* @author Jie.Yuan
*
*/
public class JdbcUtils {
/**
* 1. 初始化C3P0连接池
*/
private static DataSource dataSource;
static {
dataSource = new ComboPooledDataSource();
}
/**
* 2. 创建DbUtils核心工具类对象
*/
public static QueryRunner getQueryRuner(){
// 创建QueryRunner对象,传入连接池对象
// 在创建QueryRunner对象的时候,如果传入了数据源对象;
// 那么在使用QueryRunner对象方法的时候,就不需要传入连接对象;
// 会自动从数据源中获取连接(不用关闭连接)
return new QueryRunner(dataSource);
}
}
接下来准备实体类,注意由于要用到DbUtils组件,所以实体类中的属性要与数据库的字段一样
public class Employee {
private int empId; // 员工id
private String empName; // 员工名称
private int dept_id; // 部门id
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public int getDept_id() {
return dept_id;
}
public void setDept_id(int deptId) {
dept_id = deptId;
}
}
接下来写分页的工具类,这个类中包含五个属性:当前页,总记录数,总页数,每页的行数,每次查询的
数据
public class PageBean<T> {
private int currentPage = 1; // 当前页, 默认显示第一页
private int pageCount = 4; // 每页显示的行数(查询返回的行数), 默认每页显示4行
private int totalCount; // 总记录数
private int totalPage; // 总页数 = 总记录数 / 每页显示的行数 (+ 1)
private List<T> pageData; // 分页查询到的数据
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 int getTotalPage() {
if(totalCount%pageCount==0){
this.totalCount=totalCount%pageCount;
}else{
this.totalCount=totalCount%pageCount+1;
}
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public List<T> getPageData() {
return pageData;
}
public void setPageData(List<T> pageData) {
this.pageData = pageData;
}
}
接下来我们准备dao,前面我们在分页类中还需要获得总记录数和查询到的数据
public interface UserDao {
public int getTotalCount();
public void getPageData(PageBean<Employee> pb);
}
接下来实现这两个接口,记住步骤:准备sql语句,获得JdbcUtil的QueryRunner使用query()方法执行sql语句
在sql语句中的分页语句是select * from 表 limt ?,?分别是查询的起始行和查询的行数
package cn.itcast.dao.impl;
import java.sql.SQLException;
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 cn.itcast.dao.UserDao;
import cn.itcast.entity.Employee;
import cn.itcast.utils.JdbcUtils;
import cn.itcast.utils.PageBean;
public class UserDaoImpl implements UserDao{
@Override
public int getTotalCount() {
String sql="select count(*) from Employee";
try {
QueryRunner qr = JdbcUtils.getQueryRuner();
Long count=qr.query(sql, new ScalarHandler<Long>());
return count.intValue();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void getPageData(PageBean<Employee> pb) {
int totalCount=getTotalCount();
pb.setTotalCount(totalCount);
if(pb.getCurrentPage()<1){
pb.setCurrentPage(1);
}else if(pb.getCurrentPage()>pb.getTotalPage()){
pb.setCurrentPage(pb.getTotalPage());
}
try {
int first=(pb.getCurrentPage()-1)*pb.getPageCount();
int count=pb.getPageCount();
String sql="select * from Employee limit ?,?";
QueryRunner qr = JdbcUtils.getQueryRuner();
List<Employee> list=qr.query(sql, new BeanListHandler<Employee>(Employee.class),first,count);
pb.setPageData(list);
} catch (SQLException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
}
接下来是我们业务逻辑层接口的设计,我们在数据访问层中的一个获得总记录方法在获得查询数据方法中填充了,我们只需要在业务逻辑层实现分页查询数据接口就可以
package cn.itcast.service;
import cn.itcast.entity.Employee;
import cn.itcast.utils.PageBean;
public interface IEmployeeService {
public void getAll(PageBean<Employee> pb);
}
接下来实现这个
public class UserDaoService implements IEmployeeService{
private UserDao userDao = new UserDaoImpl();
public void getAll(PageBean<Employee> pb) {
userDao.getPageData(pb);
}
}
接下来我们写控制层,我们先获得视图层传来的当前页值,将当前页值转换整形,传给pageBean中的当前页,调用service方法的分页方法将pageBean类填充分页数据,将对象传回页面
public class IndexServlet extends HttpServlet {
// 创建Service实例
private IEmployeeService employeeService = new EmployeeService();
// 跳转资源
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<Employee> pageBean = new PageBean<Employee>();
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);
}
}
接下来我们来完成显示的页面
<%@ 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">
</head>
<body>
<table border="1" width="80%" align="center" 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="emp" items="${requestScope.pageBean.pageData}" varStatus="vs">
<tr>
<td>${vs.count }</td>
<td>${emp.empId }</td>
<td>${emp.empName }</td>
</tr>
</c:forEach>
</c:when>
<c:otherwise>
<tr>
<td colspan="3">对不起,没有你要找的数据</td>
</tr>
</c:otherwise>
</c:choose>
<tr>
<td colspan="3" align="center">
当前${requestScope.pageBean.currentPage }/${requestScope.pageBean.totalPage }页
<a href="${pageContext.request.contextPath }/index?currentPage=1">首页</a>
<a href="${pageContext.request.contextPath }/index?currentPage=${requestScope.pageBean.currentPage-1}">上一页 </a>
<a href="${pageContext.request.contextPath }/index?currentPage=${requestScope.pageBean.currentPage+1}">下一页 </a>
<a href="${pageContext.request.contextPath }/index?currentPage=${requestScope.pageBean.totalPage}">末页</a>
</td>
</tr>
</table>
</body>
</html>
到这里我们就完成分页了