javaweb 实现分页

分页原理

什么是分页技术

分页,是一种将所有数据分段展示给用户的技术.用户每次看到的不是全部数据,而是其中的一部分,如果在其中没有找到自习自己想要的内容,用户可以通过制定页码或是翻页的方式转换可见内容,直到找到自己想要的内容为止.其实这和我们阅读书籍很类似

分页的意义

分页确实有效,但它一定会加大系统的复杂度,但可否不分页呢?如果数据量少的话当然可以.但是对于企业信息系统来说数据量不会限制在一个小范围内.如果不顾一切的Select * from某个表,再将返回的数据一古脑的扔给客户,即使客户能够忍受成千上万足够让人眼花缭乱的表格式数据,繁忙的网络,紧张的服务器也会提出它们无声的抗议,甚至有时会以彻底的罢工作为终结.这个结局有点像古代为所欲为的暴君和他忍无可忍的臣民之间的故事.

程序员不是暴君,他希望程序使生活变得更好而不是更糟.考虑到企业信息系统多是三层甚至更多层架构的事实,程序员在向客户展示数据时都应该采取分页的形式.如果他不想被抱怨淹没或是半夜被电话惊醒的话.

如何实现

首先我们看一下在mysql 和Oracle中是如何分页查询的

  • mysql中的分页

    `SELECT * FROM uploadfiles LIMIT 0,5;

    `

    我们看到共查询到了5条数据

    要注意 limit 是从0开始计算的 后一个数是一次查询的记录数

  • Oracle中的分页

    在Oracle数据库中,分页方式没有MySql这样简单,它需要依靠rownum来实现.Rownum表示一条记录的行号,值得注意的是它在获取每一行后才赋予.因此,想指定rownum的区间来取得分页数据在一层查询语句中是无法做到的,要分页还要进行一次查询.示例如下:

select * from (select s.*, rownum rn from s_emp s) where rn between 6 and 10;

原理我们明白了,那怎么在Javawe应用中实现呢?

  1. 首先我们需要一个用于分页的工具类
package com.lgh.app.page;
/**
 * @author lgh
 *
 * 此类是用于分页的工具类
 * 可以重复利用
 * */
import java.util.List;

public class Page<T> {
    //当前是第几页
    private int pageNo ;
    //当前页的List
    private List<T> list;

    //每页显示多少条记录
        private int pageSize = 0;

        //共有多少条记录
        private long totalItemNumber;

        //构造器中需要对 pageNo 进行初始化
        public Page(int pageNo) {
            super();
            this.pageNo = pageNo;
        //  System.out.println("page构造方法中的pageNO "+ this.pageNo );
        }

        //需要校验一下
        public int getPageNo() {
        //  System.out.println("page  getPageNo方法开始时中的pageNO "+ this.pageNo );
            if(pageNo < 0)
                pageNo = 1;
            if(getTotalItemNumber()==0){
                return 1;
            }
            if(pageNo > getTotalPageNumber()){
                pageNo = getTotalPageNumber();
            }

            return pageNo;
        }

        public long getTotalItemNumber() {
            return totalItemNumber;
        }

        public void setPageSize(int pageSize) {
            this.pageSize = pageSize;
        }

        public int getPageSize() {
            return pageSize;
        }

        public void setList(List<T> list) {
            this.list = list;
        }

        public List<T> getList() {
            return list;
        }

        //获取总页数
        public int getTotalPageNumber(){

            int totalPageNumber = (int)totalItemNumber / pageSize;

            if(totalItemNumber % pageSize != 0){
                totalPageNumber++;
            }

            return totalPageNumber;
        }

        public void setTotalItemNumber(long totalItemNumber) {
            this.totalItemNumber = totalItemNumber;
        }

        public boolean isHasNext(){
            if(getPageNo() < getTotalPageNumber()){
                return true;
            }

            return false;
        }

        public boolean isHasPrev(){
            if(getPageNo() > 1){
                return true;
            }

            return false;
        }

        public int getPrevPage(){
            if(isHasPrev()){
                return getPageNo() - 1;
            }

            return getPageNo();
        }

        public int getNextPage(){
            if(isHasNext()){
                return getPageNo() + 1;
            }

            return getPageNo();
        }

}

封装查询条件的类

package com.lgh.app.page;

/**
 * 封装查询条件的类
 *
 * */
public class CriterFile {

    private int pageNo;     //查询页数
    private String textName;  //检索条件
    private String descValue;  //  用户输入的检索值

    public int getPageNo() {
        return pageNo;
    }

    public void setPageNo(int pageNo) {
        this.pageNo = pageNo;
    }

    public CriterFile(int pageNo) {
        super();
        this.pageNo = pageNo;
    }

    public String getTextName() {
        if(textName==null){
            return "%%";
        }else{
            textName = "%"+textName+"%";
            return textName;
        }
    }

    public void setTextName(String textName) {
        this.textName = textName;
    }

    public String getDescValue() {
        if(descValue==null){
            return "%%";
        }else{
            descValue = "%"+descValue+"%";
            return descValue;
        }
    }

    public void setDescValue(String descValue) {
        this.descValue = descValue;
    }

    @Override
    public String toString() {
        return "CriterFile [pageNo=" + pageNo + "]";
    }

}
  1. 在Javaweb应用中的dao层去进行分页查询

    首先我在javaweb应用中使用了dbutils 进行数据库操作

    这是一个非常方便的工具,尤其是在进行查询时

    使用dbutils的Dao 设计

package com.lgh.app.db;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

/**
 * 封装了基本的 CRUD 的方法, 以供子类继承使用
 * 当前 DAO 直接在方法中获取数据库连接.
 * 整个 DAO 采取 DBUtils 解决方案.
 * @param <T>: 当前 DAO 处理的实体类的类型是什么
 */
public class Dao<T> {

    private QueryRunner queryRunner = new QueryRunner();

    private Class<T> clazz;

    public Dao() {
        Type superClass = this.getClass().getGenericSuperclass();
        if(superClass instanceof ParameterizedType){
            ParameterizedType parameterizedType = (ParameterizedType) superClass;
            Type[] typeArgs = parameterizedType.getActualTypeArguments();
            if(typeArgs != null && typeArgs.length>0){
                if(typeArgs[0] instanceof Class){
                    clazz = (Class<T>) typeArgs[0];
                //  System.out.println("dao类中的构造方法泛型类型:"+clazz.getName());
                }
            }
        }
    }

    /**
     * 返回某一个字段的值:例如返回某一条记录的 customerName, 或返回数据表中有多少条记录等.
     * @param sql
     * @param args
     * @return
     */
    public <E> E getForValue(String sql,Object ...args){
        Connection conn = null;
        try {
        //  System.out.println("getForValue方法内部泛型类型:"+clazz.getName());

            conn = JdbcUtils.getConnection();

            return (E) queryRunner.query(conn, sql,new ScalarHandler(), args);

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.releaseConnection(conn);
        }
        return null;
    }

    /**
     * 返回 T 所对应的 List
     * @param sql
     * @param args
     * @return
     */
    public List<T> getForList(String sql,Object ...args){
        Connection conn = null;
        try {
            conn = JdbcUtils.getConnection();
            return queryRunner.query(conn, sql,new BeanListHandler<>(clazz), args);

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.releaseConnection(conn);
        }
        return null;
    }

    /**
     * 返回对应的 T 的一个实例类的对象.
     * @param sql
     * @param args
     * @return
     */

    public T get(String sql ,Object ...args){
        Connection conn = null;
        try {
            conn = JdbcUtils.getConnection();
            return queryRunner.query(conn, sql,new BeanHandler<>(clazz), args);

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.releaseConnection(conn);
        }
        return null;
    }

    /**
     * 该方法封装了 INSERT、DELETE、UPDATE 操作.
     * @param sql: SQL 语句
     * @param args: 填充 SQL 语句的占位符.
     */
    public void Update(String sql,Object ...args){
        Connection conn = null;
        try {
            conn = JdbcUtils.getConnection();
            queryRunner.update(conn, sql, args);

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.releaseConnection(conn);
        }
    }
}

分页查询数据

package com.lgh.app.dao;

import java.util.List;

import com.lgh.app.beans.FileBean;
import com.lgh.app.db.Dao;
import com.lgh.app.page.CriterFile;
import com.lgh.app.page.Page;

public class PageFileDao extends Dao<FileBean> {

    public Page<FileBean> getPage(CriterFile cf ,int pageSize){

        Page page = new Page<FileBean>(cf.getPageNo());
        //得到总记录数
        page.setPageSize(pageSize);
        page.setTotalItemNumber(getCount(cf));
        System.out.println(getCount(cf));
        cf.setPageNo(page.getPageNo());
        page.setList(getPageFiles(cf, pageSize));

        return page;
    }
    /**
     * 分页查询数据
     * 根据传入的页数来返回集合
     * 当用户刚进入是 页面默认为1
     * 要查到有总共多少数据来判断可以分配多少页
     *
     * */

    public List<FileBean>   getPageFiles(CriterFile cf ,int pageSize){

            String sql = "SELECT id, name fileName, path filePath, " +
                    "filedesc fileDesc FROM uploadfiles where name like ? and filedesc like ? limit ?,? ";
            return getForList(sql,cf.getTextName(),cf.getDescValue(),(cf.getPageNo()-1)*pageSize,pageSize);
    }

    //向数据库中添加数据
    public void   saveAll(List<FileBean> beans){
        String sql = "insert into uploadfiles values(null,?,?,?)";
        for(FileBean fub : beans){
            Update(sql, fub.getFileName(),fub.getFilePath(),fub.getFileDesc());
        }
    }

    public long getCount(CriterFile cf ){
        String sql = "select count(name) from uploadfiles where name like ? and filedesc like ? ";
        return getForValue(sql,cf.getTextName(),cf.getDescValue());
    }
    public void delById(Integer id){
        String sql ="delete from uploadfiles where id = ?";
        Update(sql,id);
    }

    public FileBean getByBookId(int id){
        String sql = "select id, name fileName, path filePath, filedesc  from uploadfiles where id = ?";
        return get(sql, id);
    }
}

实现了这些类,我们的分页查询基本上就已经完成了

剩下的就是在jsp 上进项显示了

3. 查询用的servlet

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<FileBean> beans = new ArrayList<>();
        //向数据库中查询数据

        PageFileDao pfd = new PageFileDao();
        //得到要查询的页数
        String pageNoStr = request.getParameter("pagenum");
        String textName = request.getParameter("textName");
        String selectName = request.getParameter("selectName");
        int num = 1 ;
        try {
            //第一次是没有 查询页数  默认为1
            num = Integer.parseInt(pageNoStr);
        } catch (NumberFormatException e) {

        }
        /**
         * 封装查询条件的类
         *
         * */
        CriterFile cf = new CriterFile(num);
        if("bookName".equals(selectName)){
            cf.setTextName(textName);

        }else{
            cf.setDescValue(textName);
        }
    //  beans = pfd.getPageFiles(cf, 5);
        //beans = ufd.getFiles();
//      for(FileUploadBean bean : beans){
//          System.out.println(bean);
//      }

        Page<FileBean> pageFile = pfd.getPage(cf, 8);
        request.getSession().setAttribute("pageFile", pageFile);
        //request.setAttribute("beans", beans);
        request.getRequestDispatcher("/app/download.jsp").forward(request, response);

    }
  1. jsp页面显示 没有整理 比较乱
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
    <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
     <%@taglib uri="/WEB-INF/mystr.tld" prefix="ms" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>下载页面</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="bs/css/bootstrap.min.css" rel="stylesheet">
    <script src="bs/js/jquery.min.js"></script>
    <script src="bs/js/bootstrap.min.js"></script>
<script type="text/javascript" src="scripts/jquery-1.7.2.js"></script>
<script type="text/javascript">
window.onload = function(){

    var dela = document.getElementsByName("delA");
    for(var i = 0 ;i <dela.length;i++){
        var del = dela[i];
        del.onclick = function(){
        if(confirm("确定要删除吗?")){
            }else{
                return false;
                 }
               }
        }

}

$(function(){

     $("a[name=‘aname‘]").click(function(){
           // alert(123);
            var serializeVal = $(":hidden").serialize();
        //  alert(serializeVal);
            var href = this.href +"&"+ serializeVal;
            //可以用隐藏域来序列化参数 也可以直接写
            //"&selectName=${param.selectName }&textName=${param.textName }"
            window.location.href = href;
            //注意 return false 是必须的
            return false;
        //  this.href = htef;
            });

    $("#pageNum").change(function(){
        var val = $(this).val();
        val = $.trim(val);

        //1. 校验 val 是否为数字 1, 2, 而不是 a12, b
        var flag = false;
        var reg = /^\d+$/g;
        var pageNo = 0;

        if(reg.test(val)){
            //2. 校验 val 在一个合法的范围内: 1-totalPageNumber
            pageNo = parseInt(val);
            if(pageNo >= 1 && pageNo <= parseInt("${pageFile.totalPageNumber }")){
                flag = true;
            }
        }

        if(!flag){
            alert("输入的不是合法的页码.");
            $(this).val("");
            return;
        }

        //3. 页面跳转
        var href = "<%=request.getContextPath() %>/GetFileListServlet?pagenum=" + pageNo + "&" + $(":hidden").serialize();
        window.location.href = href;
    });
})

</script>
</head>
<body>
<%@include file="navbar.jsp" %>
<%-- ${pageContext.request.contextPath}--%>
<font color ="red">${message }</font>
<br>
<div class="container-fluid">
        <div class="row" style="text-align: center;">

        <form action="<%=request.getContextPath() %>/GetFileListServlet">
        请输入关键字 :<select name="selectName"><option value="bookName">书名</option> <option value="leibie">类别</option></select> <input type="text" name="textName">&nbsp;<input type="submit" value="搜索">
        </form>
        <!-- 隐藏域 让有查询条件时超链接带上查询参数 -->
        <input type="hidden" name="selectName" value="${param.selectName }"/>
        <input type="hidden" name="textName" value="${param.textName }"/>
            <div class="col-md-12">

                <table class="table table-bordered table-striped table-hover">
                    <thead>

<tr><td>文件编号</td><td>文件名</td><td>文件描述</td><td align="center">操作</td></tr>
</thead>
<tbody>
<c:forEach items="${pageFile.list }" var="bean">
<c:url value="/FileDownLoad" var="downUrl">
<c:param name="path" value="${bean.filePath}"></c:param>
<c:param name="filename" value="${bean.fileName }"></c:param>
</c:url>
<c:url value="/FileDel" var="delUrl">
<c:param name="path" value="${bean.filePath}"></c:param>
<c:param name="fileId" value="${bean.id }"></c:param>
<c:param name="pagenum" value="${pageFile.pageNo }"></c:param>
</c:url>
<tr><td>${bean.id }</td><td><a href="bookmseeage?bookid=${bean.id }"><ms:sub>${bean.fileName }</ms:sub></a></td><td>${bean.fileDesc }</td><td><a href="${downUrl }">下载</a><c:if test="${userid == 2 }">&nbsp;<a name="delA" href="${delUrl}" >删除</a></c:if></td></tr>
</c:forEach>
    </tbody>
                </table>
                <div style="text-align: center">
                <c:forEach begin="${pageFile.pageNo-3>0?pageFile.pageNo-3:1 }" end="${pageFile.pageNo+3>pageFile.totalPageNumber?pageFile.totalPageNumber:pageFile.pageNo+3 }" step="1" var="i">

                <c:choose>
                <c:when test="${pageFile.pageNo == i }">
                <b><a name="aname" href="<%=request.getContextPath() %>/GetFileListServlet?pagenum=${i}" >${i}</a></b>
                </c:when>
                <c:otherwise>
                <a name="aname" href="<%=request.getContextPath() %>/GetFileListServlet?pagenum=${i}" >${i}</a>
                </c:otherwise>
                </c:choose>

                </c:forEach>
                &nbsp;&nbsp;共${pageFile.totalPageNumber }页
                &nbsp;&nbsp;当前第${pageFile.pageNo }页&nbsp;&nbsp;
                <c:if test="${pageFile.hasPrev }">
                <a name="aname" href="<%=request.getContextPath() %>/GetFileListServlet?pagenum=1">首页</a>&nbsp;&nbsp;
                  <a name="aname" href="<%=request.getContextPath() %>/GetFileListServlet?pagenum=${pageFile.prevPage}">上一页</a>&nbsp;&nbsp;
                </c:if>
                 <c:if test="${pageFile.hasNext }">
                  <a name="aname" href="<%=request.getContextPath() %>/GetFileListServlet?pagenum=${pageFile.nextPage}">下一页</a>&nbsp;&nbsp;
                <a name="aname" href="<%=request.getContextPath() %>/GetFileListServlet?pagenum=${pageFile.totalPageNumber}">尾页</a>&nbsp;&nbsp;
                </c:if>
                &nbsp;&nbsp;
                                  转到 <input type="text" size="1"  id="pageNum"/> 页  

                </div>
            </div>
        </div>
    </div>
</body>
</html>
  • Oracle中的查询Dao设计,另一个项目的代码
package com.mav.dao.impl;

import java.math.BigDecimal;
import java.util.List;

import com.mav.dao.CustomerDao;
import com.mav.dao.Dao;
import com.mav.dao.PageCustomerDao;
import com.mav.domain.CriteriaCustomer;
import com.mav.domain.Customer;
import com.mav.page.Page;

public class PageCustomerDaoImpl extends Dao<Customer> implements PageCustomerDao {

    @Override
    public Page<Customer> getPage(CriteriaCustomer cc,int size) {
        Page page = new Page(cc.getPageNo());
        page.setPageSize(size);
        page.setTotalItemNumber(getTotalItemNumber(cc));
        cc.setPageNo(page.getPageNo());
        page.setList(getForListByCriteriaCustomer(cc, size));
        return page;
    }
    //select * from (select s.*, rownum rn from s_emp s) where rn between 6 and 10;
    @Override
    public List<Customer> getForListByCriteriaCustomer(CriteriaCustomer cc, int size) {
        String sql = "select  id,name,address,phone from (select cus.*,rownum rn from customers cus) where rn between ? and ?  ";
      List<Customer> list =getForList(sql, (cc.getPageNo()-1)*size+1,(cc.getPageNo()-1)*size+size);

        return list;
    }

    @Override
    public long getTotalItemNumber(CriteriaCustomer cc) {

        String sql = "select count(id) from customers where name like ? and address like ? and phone like ?";
        BigDecimal b = getForValue(sql,cc.getName(),cc.getAddress(),cc.getPhone());
        return b.longValue();

    }

}

到这基本上一个分页就基本上实现了

来看看显示效果把

  • 总结

    分页的实现就是要把数据库中的两个分页语句弄清楚就比较容易实现了

时间: 2024-08-10 23:27:45

javaweb 实现分页的相关文章

Javaweb 实现分页功能

package cn.zr.testpage.entity; public class User { private String name; private int age; private String hobby; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public

javaweb编写分页mysql

1.封装PageBean import java.util.List; /** * 分页的JavaBean * @author Administrator */ public class PageBean<T> { // 当前页 private int pageCode; // 总页数 // private int totalPage; // 总记录数 private int totalCount; // 每页显示的记录条数 private int pageSize; // 每页显示的数据 p

javaWeb之分页组件

page.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><div> 当前${page.pageNo } 页/共${page.totalPage } 页       <a href="${page.url }?pageNo=${page.prep}">上一页</a>       <

Spring、SpringMVC、SpringData + JPA 整合详解

原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7759874.html ---------------------------------------------------------------------------------------------------------------------------------------------------------- 笔记中提供了大量的代码示例,需要说明的是,大部分代码示例都是本

JavaWeb中的简单分页

这次主要是讲解一下通过登录后对得到的数据进行分页,首先我们新建一个登录页面login.jsp,因为我们主要学习一下分页,所以登录验证的部分不再阐述,主要代码如下: 1 <form action="pageServlet"> 2 用户名:<input type="text" name="username"><br> 3 密 码:<input type="text" name="

JavaWeb之JDBC分页/监听器(十六)

多表关联操作 1. 一对多(客户与订单表) # 一对多(客户与订单表) 0. C3P0工具类 1. 建domain类与之对应要建立相应的表结构 Customer表 private int id; private String name; private List<Orders> orders = new ArrayList<Orders>(); Orders表 private int id; private String num; private float money; priv

住javaWeb分页实现(模拟百度首页)

本文来源于 http://blog.csdn.net/tjpu_lin/article/details/41050475 近期在开发一个项目,项目中有非常多数据展示的模块.所以要用到分页,网上搜了非常多分页的样例,可是非常多实现的方法和自身的代码实例耦合度太高.导致直接拿来用根本不行. 于是自己仅仅能亲自上阵了,关于分页实现大体逻辑是前台须要和后台相互传递页面參数(比如当前页面,页面大小.总共页数等),后台主要接受前台穿过来的pageNum(当前页码),进行数据查询,然后查完数据后返回给前台的同

JavaWeb分页显示内容——数据库分页查询

转载请注明原文地址: 在开发过程中,经常做的一件事,也是最基本的事,就是从数据库中查询数据,然后在客户端显示出来.当数据少时,可以在一个页面内显示完成.然而,如果查询记录是几百条.上千条呢?直接一个页面显示完全的话,表格得多长啊......这时,我们可以用分页技术. 何为分页?效果图如下: 这里总共查询了100条记录,如果一次性显示的话表格会很多行,用户体验不佳.而我们采用分页显示的话,一页显示10条记录,共十页.用户可以自行翻阅,记录少,清晰显示. 下面谈谈分页效果的实现,思路有两种: 其一:

详谈javaWeb分页的实现(模拟百度分页)

本文出自 http://blog.csdn.net/tjpu_lin/article/details/41050475 最近在开发一个项目,项目中有很多数据展示的模块,所以要用到分页,网上搜了很多分页的例子,但是很多实现的方法和自身的代码实例耦合度太高,导致直接拿来用根本不行. 于是自己只能亲自上阵了,关于分页实现大体逻辑是前台需要和后台相互传递页面参数(例如当前页面,页面大小,总共页数等),后台主要接受前台穿过来的pageNum(当前页码),进行数据查询,然后查完数据后返回给前台的同时也要将页