Servlet查询分页之物理分页

Servlet查询分页物理分页

逻辑分页

一次从数据库中把所有数据读取到内存中, 在内存中进行数据切分,然后传到前端页面。

物理分页

在查询数据库时就按照页数只取需要的数据,不在内存中处理

分页的主要思路

物理分页
思路
  1. 前端页面发起请求,要展示一页数据。 把当前要展示的页码每页展示条数传给后台
  2. 根据要展示的页码数每页展示条数去数据库中查询对应页码、条数的数据
  3. 后台需要额外查询总数据条数, 根据总数据条数每页展示条数计算出总页数
一共涉及到的参数
  • 当前展示页码: currentPage (由前端页面决定)

  • 每页展示条数: pageSize (由前端页面决定)

  • 总数据条数: totalCount (从数据库查询得来)

  • 总页数: totalPage (由totalCount 和 pageSize计算而来)

    比如说: 总记录条数是100条,每页展示10条,一共多少页? — 10

    再比如说: 总记录条数是102条,每页展示10条,一共多少页? — 11

    也就是说:

    totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;

  • 当前页对应的数据: List data; (从数据库查询得来)

分页语句

案例:假设我要从MySQL中student表中查询第2页的数据,每页展示20

第1页: 01 ~ 20

第2页: 21 ~ 40

第3页: 41 ~ 60

要显示第n页的范围公式: (n-1)*pageSize+1 ~ n*pageSize
结合MySQL中的语法,得到MySQL中分页公式:

-- limit后面的两个参数代表:
-- 第一个: 跳过多少条
-- 第二个: 取多少条数据
-- MySQL中分页语法: 
select * from student limit (n-1)*pageSize, pageSize;  

物理分页实现代码

  1. 导包导入到/WebContent/WEB-INF/lib/

druid-1.1.10.jar
jstl-1.2.jar
mysql-connector-java-5.1.47.jar

index.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
	<a href="physical?currentPage=1&pageSize=20">物理分页</a>
	<br />
	
</body>
</html>
在utils包中创建工具类
  1. 创建连接数据库的utils类
package com.lanou3g.utils;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSource;

/**
 * 数据库相关工具类
 * 
 *
 */
public class DBTools {
	
	//定义常量
	private static String PROP_DRIVERCLASSNAME = "com.mysql.jdbc.Driver";
	private static String PROP_URL = "jdbc:mysql://localhost:3306/jsp_01?characterEncoding=utf8";
	private static String PROP_USERNAME = "root";
	private static String PROP_PASSWORD = "123456";
	
	private static DruidDataSource ds;
	
	static {
		try {
			Class.forName(JDBC_DRIVER);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取数据源
	 * @return
	 */
	public static DataSource getDataSource() {
		if(ds != null) {
			return ds;
		}
		DruidDataSource ds = new DruidDataSource();
		ds.setUrl(JDBC_URL);
		ds.setUsername(JDBC_USERNAME);
		ds.setPassword(JDBC_PASSWORD);
		ds.setMaxActive(5);
		ds.setMinIdle(1);
		return ds;
	}
	
	public static Connection getConnection() throws SQLException {
		return getDataSource().getConnection();
	}
	
	public static void main(String[] args) throws SQLException {
		DataSource ds = DBTools.getDataSource();
		System.out.println(ds.getConnection());
	}
	
}

bean包中创建实体类

根据数据库创建student实体类

package com.lanou3g.bean;

import java.sql.Timestamp;

public class Student {
	private Integer id;
	private String sname;
	private String subject;
	private String tel;
	private String addr;
	private Timestamp createtime;
	public Student() {
		
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getAddr() {
		return addr;
	}
	public void setAddr(String addr) {
		this.addr = addr;
	}
	public Timestamp getCreatetime() {
		return createtime;
	}
	public void setCreatetime(Timestamp createtime) {
		this.createtime = createtime;
	}
	
}

因为要获取到五个参数
当前页(currentPage) 当前页中数据(data) 每页显示多少条(pageSize) 总数据条数(totalCount) 总页码数(totalPage)
注意:总页码数是根据数据库有多少数据来显示的所以它不用生成setter方法,它只需要生成getter方法就成了然后再算出来总共多少页
所以要在bean包中创建一个分页的实体类把上面的放在一个类中

package com.lanou3g.bean;

import java.util.List;

public class Paganation<T> {
	/**
	 * 当前要展示的页码
	 */
	private Integer currentPage;
	/**
	 * 每页展示数据的条数
	 */
	private Integer pageSize;
	/**
	 * 总数据条数
	 */
	private Integer totalCount;
	/**
	 * 总页码数
	 */
	private Integer totalPage;
	/**
	 * 当前页数据
	 */
	private List<T> data;
	/**
	 * 计算总页数
	 * @return
	 */
	public Integer getTotalPage() {
		int totalPage = getTotalCount()/getPageSize();
		if(getTotalCount()%getPageSize()!=0) {
			totalPage++;
		}
		return totalPage;
	}
	/**
	 * 返回是否有上一页
	 * @return
	 */
	public boolean hasPre() {
		return getCurrentPage()>1;
	}
	/**
	 * 返回是否有下一页
	 * @return
	 */
	public boolean hasNext() {
		return getCurrentPage()<getTotalPage();
	}
	
	public Integer getCurrentPage() {
		return currentPage;
	}
	public void setCurrentPage(Integer currentPage) {
		this.currentPage = currentPage;
	}
	public Integer getPageSize() {
		return pageSize;
	}
	public void setPageSize(Integer pageSize) {
		this.pageSize = pageSize;
	}
	public Integer getTotalCount() {
		return totalCount;
	}
	public void setTotalCount(Integer totalCount) {
		this.totalCount = totalCount;
	}
	public List<T> getData() {
		return data;
	}
	public void setData(List<T> data) {
		this.data = data;
	}
	
	
	
}

根据分页的思路创建servlet

创建PhysicalPageServlet

package com.lanou3g.web;

import java.io.IOException;
import java.util.List;

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 com.lanou3g.bean.Paganation;
import com.lanou3g.bean.Student;
import com.lanou3g.dao.StudentDao;

/**
 * 物理分页
 * @author John
 *
 */
@WebServlet("/physical")
public class PhysicalPageServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	StudentDao studentDao = new StudentDao();
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 默认展示第一页
		int currentPage = 1;
		try {
			currentPage = Integer.parseInt(request.getParameter("currentPage"));
		} catch (NumberFormatException e) {
		}
		// 默认每页展示20条
		int pageSize = 20;
		try {
			pageSize = Integer.parseInt(request.getParameter("pageSize"));
		} catch (NumberFormatException e) {
		}
		// 将前台传递过来的参数封装page对象中
		Paganation<Student> page = new Paganation<Student>();
		page.setCurrentPage(currentPage);
		page.setPageSize(pageSize);
		// 调用dao层方法,完成物理分页查询, 分页参数和数据会在dao方法中都封装到page对象里
		studentDao.findByPhysicalPage(page);
		// 将page对象放入请求域
		request.setAttribute("page", page);
		// 转发到学生列表页
		request.getRequestDispatcher("student_list.jsp").forward(request, response);
		
	}
}
创建连接数据库dao层包

创建一个studentdao类

package com.lanou3g.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.lanou3g.bean.Paganation;
import com.lanou3g.bean.Student;
import com.lanou3g.utils.DBTools;

/**
 * Student表分页查询
 *
 */
public class StudentDao {

	/**
	 * 物理分页
	 * 
	 * @param page
	 */
	public void findByPhysicalPage(Paganation<Student> page) {

		// 从page对象中拿出前端传过来的两个参数: 当前页、页面大小
		Integer currentPage = page.getCurrentPage();
		Integer pageSize = page.getPageSize();

		// 后台需要往page中补充剩下的三个参数: 总记录条数、当前页的数据、总页数
		
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			
			// 拿总记录数(totalCount): select count(*) from student;
			String sql = "select count(*) as total_count from student;";
			conn = DBTools.getConnection();
			pstmt = conn.prepareStatement(sql);
			rs = pstmt.executeQuery();
			if(rs.next()) {
				int totalCount = rs.getInt("total_count");
				// 将总记录条数封装到page对象中
				page.setTotalCount(totalCount);
			}
			rs.close();
			pstmt.close();
		
			
			// 第n页数据范围: (n-1)*pageSize+1 ~ n * pageSize 
			// MySQL写法: limit (n-1)*pageSize, pageSize
			List<Student> studentList = new ArrayList<Student>();
			sql = "select * from student limit ?,?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, (currentPage - 1) * pageSize);
			pstmt.setInt(2, pageSize);
			rs = pstmt.executeQuery();
			while(rs.next()) {
				Student student = new Student();
				student.setId(rs.getInt("id"));
				student.setSname(rs.getString("sname"));
				student.setSubject(rs.getString("subject"));
				student.setTel(rs.getString("tel"));
				student.setAddr(rs.getString("addr"));
				student.setCreatetime(rs.getTimestamp("createtime"));
				studentList.add(student);
			}
			// 将当前页数据封装到page对象中
			page.setData(studentList);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

}

最后前端页面接收后台返回的数据

student_list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>学生列表</title>
<style type="text/css">
	* {
		margin: 0;
		padding: 0;
	}
	
	table {
		border-collapse: collapse;
		margin: 100px auto;
	}
	td,th {
		border: 1px solid #888;
		padding: 3px 8px;
		text-align: center;
	}
	
	.pageBar>a {
		text-decoration: none;
		border: 1px solid blue;
		padding: 3px 5px;
		margin-left: 10px;
		color: white;
		border-radius: 3px;
		background-color: lightblue;
	}
	
	.pageBar>span {
		border: 1px solid #999;
		padding: 3px 5px;
		margin-left: 10px;
		color: white;
		border-radius: 3px;
		background-color: #ccc;
	}
	
	.pageBar {
		border: none;
		padding-top: 10px; 
	}
	
	.pageBar>.text {
		border: none;
	}

</style>
</head>
<body>
	<table>
		<caption>学生信息表</caption>
		<tr>
			<th>学号</th>
			<th>姓名</th>
			<th>学科</th>
			<th>电话</th>
			<th>住址</th>
			<th>入学时间</th>
		</tr>
		<c:forEach var="stu" items="${page.data }">
			<tr>
				<td>${stu.id }</td>
				<td>${stu.sname }</td>
				<td>${stu.subject }</td>
				<td>${stu.tel }</td>
				<td>${stu.addr }</td>
				<td>${stu.createtime }</td>
			</tr>
		</c:forEach>
		<tr>
			<td colspan="6" class="pageBar">
				<!-- 当前页大于1时,说明还有上一页,这时首页和上一页都可以点击 -->
				<c:if test="${page.currentPage > 1 }">
					<a href="physicalPageServlet?currentPage=1&pageSize=20">首页</a>
					<a href="physical?currentPage=${page.currentPage-1 }&pageSize=20">上一页</a>
				</c:if>
				<!-- 当前页小于等于1时,说明已经是第一页了,这时首页和上一页都不能点击 -->
				<c:if test="${page.currentPage <= 1 }">
					<span>首页</span>
					<span>上一页</span>
				</c:if>
				
				<span class="text">
				当前页码: ${page.currentPage } / ${page.totalPage }
				</span>
				
				<!-- 当前页小于总页数时,说明还没到最后一页,这时尾页和下一页都可以点击 -->
				<c:if test="${page.currentPage < page.totalPage }">
					<a href="physical?currentPage=${page.currentPage+1 }&pageSize=20">下一页</a>
					<a href="physical?currentPage=${page.totalPage }&pageSize=20">尾页</a>
				</c:if>
				<!-- 当前页大于等于总页数时,说明还已经到最后一页,这时尾页和下一页都不可以点击 -->
				<c:if test="${page.currentPage >= page.totalPage }">
					<span>下一页</span>
					<span>尾页</span>
				</c:if>
			</td>
		</tr>
	</table>

</body>
</html>

最后的结果的就是如下所示物理分页成功
孩子大了!该打个模糊的码了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值