Java Web学习笔记08:分页技术

分页简介

分页功能在网页中是非常常见的一个功能,其作用也就是将数据分割成多个页面来进行显示。

使用场景:
当取到的数据量达到一定的时候,就需要使用分页来进行数据分割。
当我们不使用分页功能的时候,会面临许多的问题:

客户端的问题: 如果数据量太多,都显示在同一个页面的话,会因为页面太长严重影响到用户的体验,也不便于操作,也会出现加载太慢的问题。
服务端的问题: 如果数据量太多,可能会造成内存溢出,而且一次请求携带的数据太多,对服务器的性能也是一个考验。
分页的分类
分页的实现分为真分页和假分页两种,也就是物理分页和逻辑分页。

1.真分页(物理分页):
实现原理: SELECT * FROM xxx [WHERE…] LIMIT #{param1}, #{param2}
第一个参数是开始数据的索引位置
第二个参数是要查询多少条数据
优点: 不会造成内存溢出
缺点: 翻页的速度比较慢
2.假分页(逻辑分页):

实现原理: 一次性将所有的数据查询出来放在内存之中,每次需要查询的时候就直接从内存之中去取出相应索引区间的数据
优点: 分页的速度比较快
缺点: 可能造成内存溢出
传统的分页方式
对于假分页的实现方式很简单,只需要准备一个集合保存从数据库中取出的所有数据,然后根据当前页面的码数,取出对应范围的数据显示就好了,我们这里基于物理分页来实现。

分页的原理

在这里插入图片描述

页面中的数据有:
结果集:通过 SQL 语句查询得来的——List
分页条中的数据有:
当前页:用户传递到后台——currentPage
总页数:计算的来——totalPage
上一页:计算的来——prePage
下一页:计算的来——nextPage
尾页:计算的来(总页数)——lastPage
页面大小(即每一页显示的条数):用户传递到后台——count
总条数:通过 SQL 语句查询得来的——totalCount
可以发现页面功能中需要用到的数据有两个是需要通过 SQL 语句查询得来的:一个是页面中显示的数据 List ,另一个是数据的总条数 totalCount,分别对应以下两条 SQL 语句:

SELECT * FROM student LIMIT #{param1}, #{param2}
SELECT COUNT(*) FROM student
通过计算得到的数据有:

总页数:totalPage
总页数 = 总条数 % 页面大小 == 0 ? 总条数 / 页面大小 : 总条数 / 页面大小 + 1
上一页:prePage
上一页 = 当前页 - 1 > = 1 ? 当前页 - 1 : 1
下一页:nextPage
下一页 = 当前页 + 1 <= totalPage ? 当前页 + 1 : totalPage
尾页:lastPage
尾页 = 总条数 % 页面大小 == 0 ? 总条数 - 页面大小 : 总条数 - 总条数 % 页面大小
用户传递的数据:

当前页:currentPage
页面大小:count

二、案例演示:硬分页显示新闻列表

1、创建Web项目PagingNews
在这里插入图片描述
2、在web目录里创建META-INF目录,在里面创建数据源配置文件context.xml
在这里插入图片描述

<?xml version="1.0" encoding="utf-8" ?>
<Context>
    <Resource
            name="qing/news" auth="Container"
            type="javax.sql.DataSource"
            maxAlive="100" maxIdle="30" maxWait="1000"
            driverClassName="com.mysql.jdbc.Driver"
            url="jdbc:mysql://localhost:3306/qing"
            username="root" password="1"

    />

</Context>

3、在src里创建net.qing.news.bean包,在里面创建新闻实体类News
在这里插入图片描述

package net.qing.news.bean;

import java.sql.Timestamp;

public class news {
    private int nid;
    private int ntid;
    private String ntname;
    private String ntitle;
    private String nauthor;
    private Timestamp ncreatedate;
    private String npicpath;
    private String ncontent;
    private Timestamp nmodifydate;
    private String nsummary;

    public int getNid() {
        return nid;
    }

    public void setNid(int nid) {
        this.nid = nid;
    }

    public int getNtid() {
        return ntid;
    }

    public void setNtid(int ntid) {
        this.ntid = ntid;
    }

    public String getNtname() {
        return ntname;
    }

    public void setNtname(String ntname) {
        this.ntname = ntname;
    }

    public String getNtitle() {
        return ntitle;
    }

    public void setNtitle(String ntitle) {
        this.ntitle = ntitle;
    }

    public String getNauthor() {
        return nauthor;
    }

    public void setNauthor(String nauthor) {
        this.nauthor = nauthor;
    }

    public Timestamp getNcreatedate() {
        return ncreatedate;
    }

    public void setNcreatedate(Timestamp ncreatedate) {
        this.ncreatedate = ncreatedate;
    }

    public String getNpicpath() {
        return npicpath;
    }

    public void setNpicpath(String npicpath) {
        this.npicpath = npicpath;
    }

    public String getNcontent() {
        return ncontent;
    }

    public void setNcontent(String ncontent) {
        this.ncontent = ncontent;
    }

    public Timestamp getNmodifydate() {
        return nmodifydate;
    }

    public void setNmodifydate(Timestamp nmodifydate) {
        this.nmodifydate = nmodifydate;
    }

    public String getNsummary() {
        return nsummary;
    }

    public void setNsummary(String nsummary) {
        this.nsummary = nsummary;
    }

    @Override
    public String toString() {
        return "news{" +
                "nid=" + nid +
                ", ntid=" + ntid +
                ", ntname='" + ntname + '\'' +
                ", ntitle='" + ntitle + '\'' +
                ", nauthor='" + nauthor + '\'' +
                ", ncreatedate=" + ncreatedate +
                ", npicpath='" + npicpath + '\'' +
                ", ncontent='" + ncontent + '\'' +
                ", nmodifydate=" + nmodifydate +
                ", nsummary='" + nsummary + '\'' +
                '}';
    }
}

4、创建net.qing.news.dbutil包,在里面创建数据库连接管理类ConnectionManager
在这里插入图片描述

package net.qing.news.dbutil;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * 功能:数据库连接管理类
 * 作者:卿加波
 * 日期:2019年11月14日
 */
public class ConnectionManager {
    /**
     * 私有化构造方法,拒绝实例化
     */
    private ConnectionManager() {
    }

    /**
     * 获取数据库连接静态方法
     *
     * @return 数据库连接
     */
    public static Connection getConnection() {
        Connection conn = null;
        try {
            // 创建初始化上下文
            Context ctx = new InitialContext();
            // 通过数据库连接池查询获取数据源
            DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/news");
            // 通过数据源获取数据库连接
            conn = ds.getConnection();
        } catch (NamingException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 关闭数据库连接静态方法
     *
     * @param conn 数据库连接
     */
    public static void closeConn(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

5、创建net.qing.news.dao包,在里面创建新闻数据访问类NewsDao
在这里插入图片描述

package net.qing.news.dao;



import net.qing.news.bean.News;
import net.qing.news.dbutil.ConnectionManager;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 功能:新闻数据访问类
 * 作者:卿加波
 * 日期:2019年11月14日
 */
public class NewsDao {
    /**
     * 获取全部新闻列表
     *
     * @return 全部新闻列表
     */
    public List<News> findAllNews() {
        // 定义新闻列表
        List<News> newsList = new ArrayList<>();

        // 获取数据库连接
        Connection conn = ConnectionManager.getConnection();
        // 定义SQL字符串
        String strSQL = "select * from news";
        try {
            // 创建语句对象
            Statement stmt = conn.createStatement();
            // 执行SQL查询,返回结果集
            ResultSet rs = stmt.executeQuery(strSQL);
            // 遍历结果集
            while (rs.next()) {
                // 创建新闻实体对象
                News news = new News();
                // 将当前记录字段用于设置新闻实体属性
                news.setNid(rs.getInt("nid"));
                news.setNtid(rs.getInt("ntid"));
                news.setNtitle(rs.getString("ntitle"));
                news.setNauthor(rs.getString("nauthor"));
                news.setNcreatedate(rs.getTimestamp("ncreatedate"));
                news.setNpicpath(rs.getString("npicpath"));
                news.setNcontent(rs.getString("ncontent"));
                news.setNmodifydate(rs.getTimestamp("nmodifydate"));
                news.setNsummary(rs.getString("nsummary"));
                // 将当前新闻实体添加到新闻列表
                newsList.add(news);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭数据库连接
            ConnectionManager.closeConn(conn);
        }

        // 返回新闻列表
        return newsList;
    }

    /**
     * 获取总记录数
     *
     * @return 总记录数
     */
    public int getCount() {
        // 返回总记录数
        return findAllNews().size();
    }

    /**
     * 获取总页数
     *
     * @param count 总记录数
     * @param pageSize 每页记录数
     * @return 总页数
     */
    public int getTotalPages (int count, int pageSize) {
        // 返回总页数
        return count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
    }

    /**
     * 按页获取新闻列表
     *
     * @param currentPage 当前页码
     * @param pageSize 每页记录数
     * @return 当前页新闻列表
     */
    public List<News> findNewsByPage(int currentPage, int pageSize) {
        // 定义新闻列表
        List<News> newsList = new ArrayList<>();

        // 获取数据库连接
        Connection conn = ConnectionManager.getConnection();
        // 定义SQL字符串
        String strSQL = "select * from news limit ?, ?";
        try {
            // 创建预备语句对象
            PreparedStatement pstmt = conn.prepareStatement(strSQL);
            // 设置占位符的值
            pstmt.setInt(1, pageSize * (currentPage - 1));
            pstmt.setInt(2, pageSize);
            // 执行SQL查询,返回结果集
            ResultSet rs = pstmt.executeQuery();
            // 遍历结果集
            while (rs.next()) {
                // 创建新闻实体对象
                News news = new News();
                // 将当前记录字段用于设置新闻实体属性
                news.setNid(rs.getInt("nid"));
                news.setNtid(rs.getInt("ntid"));
                news.setNtitle(rs.getString("ntitle"));
                news.setNauthor(rs.getString("nauthor"));
                news.setNcreatedate(rs.getTimestamp("ncreatedate"));
                news.setNpicpath(rs.getString("npicpath"));
                news.setNcontent(rs.getString("ncontent"));
                news.setNmodifydate(rs.getTimestamp("nmodifydate"));
                news.setNsummary(rs.getString("nsummary"));
                // 将当前新闻实体添加到新闻列表
                newsList.add(news);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭数据库连接
            ConnectionManager.closeConn(conn);
        }

        // 返回新闻列表
        return newsList;
    }
}

6、在web目录里创建首页文件index.jsp
在这里插入图片描述
7、在web目录里创建不分页显示全部新闻页面allnews.jsp

<%@ page import="net.qing.news.dao.NewsDao" %>
<%@ page import="net.qing.news.bean.News" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>不分页显示全部新闻列表</title>
</head>
<body>
<%
    // 创建新闻数据访问对象
    NewsDao newsDao = new NewsDao();
    // 获取全部新闻列表
    List<News> newsList = newsDao.findAllNews();
    // 在页面上显示数据
    out.print("<table border='1' cellpadding='10'>");
    out.print("<tr><th>编号</th><th>标题</th><th>创建时间</th></tr>");
    // 遍历新闻列表
    for (News news: newsList) {
        out.print("<tr><td>" + news.getNid() + "</td>");
        out.print("<td>" + news.getNtitle() + "</td>");
        out.print("<td>" + news.getNcreatedate() + "</td></tr>");
    }
    out.print("</table>");
%>
</body>
</html>

8、查看效果

在这里插入图片描述
9、在web目录里创建分页显示全部新闻列表页面pagingnews.jsp

在这里插入图片描述

<%--
  Created by IntelliJ IDEA.
  User: lenovo
  Date: 2019/11/14
  Time: 10:36
  To change this template use File | Settings | File Templates.
--%>
<%@ page import="net.qing.news.dao.NewsDao" %>
<%@ page import="net.qing.news.bean.News" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>分页显示全部新闻列表</title>
</head>
<body>
<%
    // 创建新闻数据访问对象
    NewsDao newsDao = new NewsDao();
    // 获取总记录数
    int count = newsDao.getCount();
    // 定义每页记录数
    int pageSize = 5;
    // 获取总页数
    int totalPages = newsDao.getTotalPages(count, pageSize);
    // 获取当前页码
    String currentPage = request.getParameter("pageIndex");
    // 首次进入页面,应该显示第一页内容
    if (currentPage == null) {
        currentPage = "1";
    }
    // 获取页索引
    int pageIndex = Integer.parseInt(currentPage);
    // 对首页与末页的页索引进行控制
    if (pageIndex < 1) {
        pageIndex = 1;
    } else if (pageIndex > totalPages) {
        pageIndex = totalPages;
    }

    // 获取当前页新闻列表
    List<News> newsList = newsDao.findNewsByPage(pageIndex, pageSize);
    // 在页面上显示数据
    out.print("<table border='1' cellpadding='10' style='margin: 0px auto'>");
    out.print("<tr><th>编号</th><th>标题</th><th>创建时间</th></tr>");
    // 遍历新闻列表
    for (News news: newsList) {
        out.print("<tr><td>" + news.getNid() + "</td>");
        out.print("<td>" + news.getNtitle() + "</td>");
        out.print("<td>" + news.getNcreatedate() + "</td></tr>");
    }
    out.print("</table>");
%>
<%-- 实现分页操作【首页、上一页、下一页、末页】--%>
<p style="text-align: center">
    <a href="pagingnews.jsp?pageIndex=1">[首页]</a>&nbsp;&nbsp;
    <a href="pagingnews.jsp?pageIndex=<%= pageIndex - 1 %>">[上一页]</a>&nbsp;&nbsp;
    <a href="pagingnews.jsp?pageIndex=<%= pageIndex + 1 %>">[下一页]</a>&nbsp;&nbsp;
    <a href="pagingnews.jsp?pageIndex=<%= totalPages %>">[末页]</a>&nbsp;&nbsp;
    <%= pageIndex %> / <%= totalPages %>
</p>
</body>
</html>

10、重启tomcat服务器,查看分页显示效果
在这里插入图片描述
11、软分页例子
在这里插入图片描述

<%@ page import="net.qing.news.bean.News" %>
<%@ page import="net.qing.news.dao.NewsDao" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
  Created by IntelliJ IDEA.
  User: lenovo
  Date: 2019/11/14
  Time: 11:35
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>软分页显示新闻列表</title>
</head>
<body>
<%
    //获取总页数
    NewsDao newsDao = new NewsDao();
    int count = newsDao.getCount();
    int pageSize = 5;
    int totalPages = newsDao.getTotalPages(count, pageSize);
    List<News> allnews = newsDao.findAllNews();

    // 获取当前页码
    String currentPage = request.getParameter("pageIndex");
    if (currentPage == null) {
        currentPage = "1";
    }
    int pageIndex = Integer.parseInt(currentPage);
    //对首页与末页进行控制
    if (pageIndex < 1) {
        pageIndex = 1;
    } else if (pageIndex > totalPages) {
        pageIndex = totalPages;
    }

    // 生成当前页的新闻列表
    List<News> newsList = new ArrayList<>();
    for (int i = (pageIndex - 1) * pageSize; i < pageIndex * pageSize; i++) {
        if (i < count) {
            newsList.add(allnews.get(i));
        }
    }
    out.print("<table border='1' cellpadding='10' style='margin: 0px auto'>");
    out.print("<tr><th>编号</th><th>标题</th><th>创建时间</th></tr>");
    for (News news : newsList) {
        out.print("<tr><td>" + news.getNid() + "</td>");
        out.print("<td>" + news.getNtitle() + "</td>");
        out.print("<td>" + news.getNcreatedate() + "</td></tr>");
    }
    out.print("</table>");
%>
<p style="text-align: center">
    <a href="softpagingnews.jsp?pageIndex=1">[首页]</a>&nbsp;&nbsp;
    <a href="softpagingnews.jsp?pageIndex=<%= pageIndex - 1 %>">[上一页]</a>&nbsp;&nbsp;
    <a href="softpagingnews.jsp?pageIndex=<%= pageIndex + 1 %>">[下一页]</a>&nbsp;&nbsp;
    <a href="softpagingnews.jsp?pageIndex=<%= totalPages %>">[末页]</a>&nbsp;&nbsp;
    <%= pageIndex %> / <%= totalPages %>
</p>
</body>
</html>

12、重启服务,查看效果
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值