当数据有几万、几十万甚至上百万时,用户必须要拖动页面才能浏览更多的数据,很大程度的影响了用户体验。这时可以使用分页来显示数据,能够使数据更加清晰直观,且不受数量的限制。
分页的方式主要分为两种:
实现数据的分页显示,需要以下几个关键步骤:
确定每页显示的记录条数,即每次从数据库中需要查询出多少条记录用于页面显示。通常这个数量可以在开发时定义好,也可以由用户来选择。
根据每页显示的记录条数计算总页数,即会产生多少页数据。显示的记录数量是已知的,而数据库中符合条件的记录总数是未知的,因此想要得到总页数,需要先得到符合条件的记录总数。
使用相应的 SQL 语句实现分页需求。例如,MySQL 中的 LIMIT 子句,SqlServer 中的 TOP、Oracle 中的 ROWNUM 等。
注意:本节使用的是 MySQL 数据库。不同的数据库厂商实现分页的 SQL 语句会存在差异,因此在实际应用中根据数据库的不同,需要修改相应的 SQL 语句。
创建 website 数据表,并插入数据。点击下载 SQL 文件(下载后需要解压)。
Website 类的代码如下:
- package xyz.cdsy.entity;
-
- public class Website {
- private int id;
- private String name;
- private String url;
- private int age;
- private String country;
-
- 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 getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public String getCountry() {
- return country;
- }
-
- public void setCountry(String country) {
- this.country = country;
- }
- }
基于方便代码管理的考虑,将有关分页的数据封装到一个 Page 类中,其中包括每页显示的数据数量、数据的总数量、显示的总页数、当前页码、每页显示的数据集合。Page 代码如下:
- package xyz.cdsy.utils;
-
- import java.util.List;
-
- import xyz.cdsy.entity.Website;
-
- public class Page {
- // 总页数
- private int totalPageCount = 0;
- // 页面大小,即每页显示记录数
- private int pageSize = 3;
- // 记录总数
- private int totalCount;
- // 当前页码
- private int currPageNo = 1;
- // 每页网站集合
- private List<Website> websiteList;
-
- public int getTotalPageCount() {
- return totalPageCount;
- }
-
- public void setTotalPageCount(int totalPageCount) {
- this.totalPageCount = totalPageCount;
- }
-
- public int getPageSize() {
- return pageSize;
- }
-
- public void setPageSize(int pageSize) {
- if (pageSize > 0)
- this.pageSize = pageSize;
- }
-
- public int getTotalCount() {
- return totalCount;
- }
-
- public void setTotalCount(int totalCount) {
- if (totalCount > 0) {
- this.totalCount = totalCount;
- // 计算总页数
- totalPageCount = this.totalCount % pageSize == 0 ? (this.totalCount / pageSize)
- : (this.totalCount / pageSize + 1);
- }
- }
-
- public int getCurrPageNo() {
- if (currPageNo == 0)
- return 0;
- return currPageNo;
- }
-
- public void setCurrPageNo(int currPageNo) {
- if (currPageNo > 0)
- this.currPageNo = currPageNo;
- }
-
- public List<Website> getWebsiteList() {
- return websiteList;
- }
-
- public void setWebsiteList(List<Website> websiteList) {
- this.websiteList = websiteList;
- }
- }
在 setTotalCount() 方法中,根据记录总数和每页显示记录数计算出总页数,使用三元运算符?:进行处理。如果记录总数能被每页显示记录数整除,则总页数为两者的商,如果不能被整除,则余出的记录数单独列为一页,总页数为两者的商再加 1。
WebsiteDao 代码如下:
- package xyz.cdsy.dao;
-
- import java.util.List;
-
- import xyz.cdsy.entity.Website;
-
- public interface WebsiteDao {
- // 查询总条数
- public int getTotcalCount();
-
- //根据起始下标和每页显示数量查询数据
- public List<Website> getPageWebsiteList(int pageNo, int pagesize);
- }
WebsiteDaoImpl 代码如下:
- package xyz.cdsy.dao;
-
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.List;
-
- import xyz.cdsy.entity.Website;
-
- public class WebsiteDaoImpl implements WebsiteDao {
- /**
- * 连接数据库
- */
- public static Connection getConnection() {
- Connection con = null;
- try {
- Class.forName("com.mysql.jdbc.Driver");
- con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
- } catch (Exception e) {
- e.printStackTrace();
- }
- return con;
- }
-
- /**
- * 查询总条数
- */
- @Override
- public int getTotcalCount() {
- int count = 0;
- try {
- Connection con = getConnection();
- String sql = "SELECT COUNT(id) FROM website";
- PreparedStatement ps = con.prepareStatement(sql);
- ResultSet rs = ps.executeQuery();
- rs.next();
- count = rs.getInt(1);
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return count;
- }
-
- @Override
- public List<Website> getPageWebsiteList(int pageNo, int pagesize) {
- PreparedStatement ps;
- ResultSet rs;
- List<Website> list = new ArrayList<Website>();
- try {
- Connection con = getConnection();
- String sql = "SELECT * FROM website LIMIT " + (pageNo - 1) * pagesize + "," + pagesize;
- ps = con.prepareStatement(sql);
- System.out.println(sql);
- rs = ps.executeQuery();
-
- while (rs.next()) {
- Website website = new Website();
- website.setId(rs.getInt(1));
- website.setName(rs.getString(2));
- website.setUrl(rs.getString(3));
- website.setAge(rs.getInt(4));
- website.setCountry(rs.getString(5));
- list.add(website);
- }
- con.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return list;
- }
- }
view.jsp 页面代码如下:
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@ page
- import="java.util.*,xyz.cdsy.dao.*,xyz.cdsy.entity.*,xyz.cdsy.utils.*"%>
- <html>
- <head>
- <title>城东书院(www.cdsy.xyz)</title>
- </head>
- <body>
- <%
- WebsiteDao websiteDao = new WebsiteDaoImpl();
- String pageNo = request.getParameter("page") != null ? request.getParameter("page") : "1";
- int currPageNo = Integer.parseInt(pageNo);
- Page p = new Page();
- p.setCurrPageNo(currPageNo);
- p.setPageSize(3);
- p.setTotalCount(websiteDao.getTotcalCount());
-
- List<Website> websiteList = websiteDao.getPageWebsiteList(p.getCurrPageNo(), p.getPageSize());
- p.setWebsiteList(websiteList);
- out.print("<h1>当前页面: " + currPageNo + "</h1>");
- out.print("<table border='1' cellpadding='4' width='60%'>");
- out.print("<tr><th>id</th><th>name</th><th>url</th><th>age</th><th>country</th></tr>");
- for (Website e : websiteList) {
- out.print("<tr><td>" + e.getId() + "</td><td>" + e.getName() + "</td><td>" + e.getUrl() + "</td><td>"
- + e.getAge() + "</td><td>" + e.getCountry() + "</td></tr>");
- }
- out.print("</table>");
- for (int i = 1; i <= p.getTotalPageCount(); i++) {
- %>
- <a href="view.jsp?page=<%=i%>"><%=i%></a>
-
- <%
- }
- %>
- </body>
- </html>
运行结果如下: