分页显示数据
前提:准备好jar包,c3p0-config.xml配置文件,以及C3P0Util工具类
除了几个jar包,之前C3P0数据库连接池带有解释
https://blog.csdn.net/weixin_43968510/article/details/90739720
新建一个JavaWeb项目
2.建立包结构
使用MVC模式(模型-视图-控制器)
各个包的作用:------>
dao层:主要是数据库的操作
entity:存放实体类
service层:业务逻辑层
util:存放工具类
web:存放servlet类
细节:------------------->
servlet类:起一个获取参数,调用业务逻辑,分发转向的作用
而像c3p0-config.xml配置文件就是在根目录下
细化的每个包下的文件
像dao,service包下存放接口,然后在imple包下再写这些接口的实现类
3.导入相关jar包
c3p0-0.9.1.2.jar是C3p0连接池的jar包
commons-dbutils-1.4.jar是DButils框架
jstl-1.2.jar是核心标签库,后面分页显示数据会用到
mysql-connector-java-5.1.37-bin.jar是MySQL数据库连接的jar包
4.先准备实体类
1.代码如下,注意包结构,以及字段名,字段类型
细节:最后一个字段 deptId不用写
package wh.entity;
/**
* 员工实体类:
* id 编号
* name 姓名
* gender 性别
* title 职位
* email
* salary 薪水
*/
public class Employee {
private int id;
private String name;
private String gender;
private String title;
private String email;
private String salary;
public Employee() {
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", title='" + title + '\'' +
", email='" + email + '\'' +
", salary='" + salary + '\'' +
'}';
}
public Employee(int id, String name, String gender, String title, String email, String salary) {
this.id = id;
this.name = name;
this.gender = gender;
this.title = title;
this.email = email;
this.salary = salary;
}
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
}
2.写PageBean实体类,存放每页数据的实体类
对于分页显示的数据,我们可以进行-------->
“首页”,“上一页”,“下一页”,“尾页”,“每页显示的记录条数”,“跳转到第几页”,“当前页”
这7个参数的改变,但是实际情况真正变化的只有三个,也就是
“当前页”,“每页显示的记录数”,“跳转到第几页”,其他参数都是围绕这三个变参进行的
比如-------->
首页,固定了就是1
上一页,就是当前页-1 (我没判断处理)
下一页,当前页+1 (我没判断处理)
尾页,就是总记录数除以每页显示的记录数
所以,真正在变化的只有3个参数
2.1写出PageBean实体类
package wh.entity;
import java.util.List;
/**
* 分页对象,用于存储当前页分页相关的数据
* 对于 "首页,上一页,下一页,尾页 "都是可以直接本事获取出
* @author wh
*/
public class PageBean {
/**当前页数据*/
List<Employee> data;
/**首页*/
int firstPage;
/**上一页*/
int prePage;
/**下一页*/
int nextPage;
/**尾页,也是总页数*/
int totalPage;
/**当前页*/
int currentPage;
/**每页显示记录数*/
int pageSize;
/**总记录数*/
int totalCount;
public List<Employee> getData() {
return data;
}
public void setData(List<Employee> data) {
this.data = data;
}
/**
* 计算首页
* 写死了就是1
* @return
*/
public int getFirstPage() {
return 1;
}
public void setFirstPage(int firstPage) {
this.firstPage = firstPage;
}
/**
* 上一页
* 算法:如果当前页为1,那么上一页就是当前页;否则就当前页-1
* @return
*
*/
public int getPrePage() {
return this.getCurrentPage()==this.getFirstPage()?1:
this.getCurrentPage()-1;
}
public void setPrePage(int prePage) {
this.prePage = prePage;
}
/**
* 下一页
* 算法:若当前页是末页,则为末页;否则为当前页+1
* @return
*/
public int getNextPage() {
return this.getCurrentPage()==this.getTotalPage()?this
.getTotalPage():
this.getCurrentPage()+1;
}
public void setNextPage(int nextPage) {
this.nextPage = nextPage;
}
/**
* 计算末页:
* 算法:如果总记录数%每页显示记录数==0
* 如果不能整数,等于总记录数/每页显示记录数+1
* @return
*/
public int getTotalPage() {
return this.getTotalCount()%this.getPageSize()==0?this.getTotalCount()/this.getPageSize()
:
this.getTotalCount()/this.getPageSize()+1;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}
上面的代码对于上一页,下一页做了判断,可以参考
4.service层,dao层的实现
4.1 dao层的接口,就两个方法
4.2 dao层的实现类
package wh.dao.imple;
import wh.dao.EmpDao;
import wh.entity.Employee;
import wh.util.C3P0Util;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.SQLException;
import java.util.List;
/**
* 员工接口的实现类
* @author wh
*
*/
public class EmpDaoImple implements EmpDao {
/**
* 提供一个查询当前员工数据的方法
*/
@Override
public List<Employee> queryData(int currentPage,int pageSize ) {
/**
* 总结 select * from employee limit (当前页页码-1)*每页显示的记录条数,每页显示的记录条数;
*/
//创建QueryRunner对象,传入数据源
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
String sql="select * from employee limit ?,?";
/**
String sql="select * from employee limit (当前页页码-1)*每页显示的记录条数,每页显示的记录条数;\n";
*/
//起始行
int startNo = (currentPage-1)*pageSize;
List<Employee> list=null;
//todo 使用JavaBean对象的list集合的实现类 BeanListHandler类封装
try {
list=qr.query(sql, new BeanListHandler<Employee>(Employee.class), new Object[]{startNo,pageSize});
return list;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 提供一个查询总记录数的方法
*
*/
@Override
public int queryCount() {
//获取QueryRunner对象,传入数据源
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
String sql="select count(*) from employee";
try {
Long count = (long) qr.query(sql, new ScalarHandler());
//将long的类型转成int类型
return count.intValue();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
List<Employee>list = new EmpDaoImple().queryData(4, 2);
for (Employee employee:list){
System.out.println(employee);
}
System.out.println(new EmpDaoImple().queryCount());
}
}
分页的核心:
select * from employee limit (当前页页码-1)*每页显示的记录条数,每页显示的记录条数
4.3 service层的接口
4.4 service的实现类
package wh.service.imple;
import wh.dao.EmpDao;
import wh.dao.imple.EmpDaoImple;
import wh.entity.Employee;
import wh.entity.PageBean;
import wh.service.EmpService;
import java.util.List;
public class EmpServiceImple implements EmpService {
/**
*
* 提供一个封装好的 PageBean对象的方法
*
*传入当前页的页数,和每页的大小
* @return
*
*/
@Override
public PageBean queryPageBean(String currentPage,int pageSize) {
//1)封装PageBean对象
PageBean pageBean = new PageBean();
//todo 显示当前页数据应该在dao层实现
//1.2)记录当前页的数据
pageBean.setCurrentPage(Integer.parseInt(currentPage));
//得到dao层的实现类对象,操作方法
EmpDao empDao = new EmpDaoImple();
//1.3)显示当前页数据
//前提:准备好总记录数和每页大小
//获取数据库的总记录数
int totalCount=empDao.queryCount();
pageBean.setTotalCount(totalCount);
//每页的数据大小
pageBean.setPageSize(pageSize);
List<Employee> list = empDao.queryData(pageBean.getCurrentPage() , pageBean.getPageSize());
//1.4)添加到PageBean对象中
pageBean.setData(list);
return pageBean;
}
}
5. web层的分发转向
package wh.web;
import wh.entity.PageBean;
import wh.service.EmpService;
import wh.service.imple.EmpServiceImple;
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 java.io.IOException;
import java.io.PrintWriter;
/**
* Web层:
* 接收用户输入的参数,第几页
* 调用业务逻辑的方法,获取结果
* 将结果转发到jsp界面显示
* @author wh
*
*/
@WebServlet(name = "ListEmpServlet",urlPatterns = ("/listEmpServlet"))
public class ListEmpServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//三步
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
//从用户参数获取当前页数据(currentPage)
String currentPage = request.getParameter("currentPage");
if (currentPage==null||currentPage.equals("")){
//如果第一次访问,没有传递currentPage参数,则当前页为1
currentPage="1";
}
//接收用户输入的每页显示数据的记录数
String pageSize = request.getParameter("pageSize");
//如果没有传递过来,设置一个默认值为2
//细节:当点击下一页或者别的,会导致pageSize丢失了,应该要带回去
if (pageSize==null||pageSize.equals("")){
//设置pageSize的默认值是2
pageSize="2";
}
//1)在service层调用获取PageBean对象的方法
EmpService empService = new EmpServiceImple();
//只需要传入一个currentPage(当前页数)即可
PageBean pageBean = empService.queryPageBean(currentPage,Integer.parseInt(pageSize));
//2)把PageBean对象放到域中
request.setAttribute("pageBean", pageBean);
//3)转发
request.getRequestDispatcher("/listEmp.jsp").forward(request, response);
}
}
转发到listEmp.jsp中
6. jsp文件负责显示结果
<%--
Created by IntelliJ IDEA.
User: ASUS
Date: 2019/4/24
Time: 9:31
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%-- 导入核心标签库 --%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>显示结果</title>
</head>
<body>
<table border="1" align="center" width="=850px">
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>职位</th>
<th>邮箱</th>
<th>薪水</th>
</tr>
<%-- 遍历域对象中pageBean中的list集合,也就是字段data --%>
<%-- forEach遍历标签 --%>
<c:forEach items="${pageBean.data}" var="emp">
<tr>
<td>${emp.id}</td>
<td>${emp.name}</td>
<td>${emp.gender}</td>
<td>${emp.title}</td>
<td>${emp.email}</td>
<td>${emp.salary}</td>
</tr>
</c:forEach>
<tr>
<%--
//todo 需求1:
1)如果当前页是首页,就不能点击上一页和首页,否则就可以点击
2)如果当前页是末页,就不能点击下一页和末页,否则就可以点击
--%>
<td align="center" colspan="6">
<c:choose>
<c:when test="${pageBean.currentPage==pageBean.firstPage}">
首页
上一页
</c:when>
<c:otherwise>
<a href="${pageContext.request.contextPath}/listEmpServlet?currentPage=${pageBean.firstPage}&pageSize=${pageBean.pageSize}">首页 </a>
<a href="${pageContext.request.contextPath}/listEmpServlet?currentPage=${pageBean.prePage}&pageSize=${pageBean.pageSize}">上一页 </a>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${pageBean.currentPage==pageBean.totalPage}">
下一页
尾页
</c:when>
<c:otherwise>
<a href="${pageContext.request.contextPath}/listEmpServlet?currentPage=${pageBean.nextPage}&pageSize=${pageBean.pageSize}">
下一页
</a>
<a href="${pageContext.request.contextPath}/listEmpServlet?currentPage=${pageBean.totalPage}&pageSize=${pageBean.pageSize}"> 尾页 </a>
</c:otherwise>
</c:choose>
当前页为第${pageBean.currentPage}页/共${pageBean.totalPage}页
总记录数是${pageBean.totalCount}条/
<%--
//todo 需求2
用户输入每页显示数据的大小
当输入完,焦点一释放就获取它的值使用js的onblur实现
--%>
每页显示<input type="text" id="pageSize" style="width: 25px" value="${pageBean.pageSize}" onblur="changePageSize()" >条
<%--
//todo 需求3:
跳转到第几页
分析:将它设计成一个下拉的列表供选择第几页
--%>
跳转到第<input type="text" id="currentPage" size="2"
value="${pageBean.currentPage}" onblur="changePage()">页
</td>
</tr>
</table>
</body>
<script type="text/javascript">
/* 改变每页显示的记录数*/
function changePageSize(){
//1.得到用户输入的数据
var pageSize = document.getElementById("pageSize").value;
//2.处理用户输出的数据
//判断规则:只能输入1-2位的数字
var reg=/^[1-9][0-9]?$/; //?表示0-1个
if (!reg.test(pageSize)){
alert("只能输入1-2位的数字!");
return;
}
//2.请求ListEmpServlet类,同时发送参数pageSize
var url="${pageContext.request.contextPath}/listEmpServlet?pageSize="+pageSize;
//请求一个地址
window.location.href=url;
}
/* 跳转指定的页数的页面 */
function changePage() {
/*获取用户输入的数据*/
var currentPage = document.getElementById("currentPage").value;
var reg=/^[1-9][0-9]?$/;
if(!reg.test(currentPage)){
alert("只能输入1-2位数字!")
return;
}
/* 如果输入的数字大于了最大页数,那么提示*/
var totalPage="${pageBean.totalPage}";
if(currentPage>totalPage){
alert("已经超过了总页数!");
return;
}
var url="${pageContext.request.contextPath}/listEmpServlet?currentPage="+currentPage+"&pageSize=${pageBean.pageSize}";
window.location.href=url;
}
</script>
</html>
1.使用到了forEach标签遍历结果集,因为结果集是一个List集合
里面存放的就是Employee实体类
通过.获取里面的字段值 ,例如${emp.id},emp只是一个别名,就是这个List集合的别名
直接forEach展示完了当前页的数据
2.
后面进行了判断,是否显示链接使用户点击,第一页的话,首页就失效!
<c:chooes>,<c:when>,<c:otherwise>这3个标签经常是一起使用的
用于判断处理,好比 if… else…