牛骨文教育服务平台(让学习变的简单)
博文笔记

基于Java实现的简单且通用的分页实现封装 <Pagiation>

创建时间:2015-09-02 投稿人: 浏览次数:4694

博客搬家了, 新地址 [ http://wuwz.org ],是时候换上HEXO了

Pagination.java (interface)

定义了分页常用的属性,方法
包名:com.app.pagination;

package com.app.pagination;
import java.util.List;
/**
 * 通用分页接口
 * @author: wuwz@live.com
 * @ClassName: Pagination
 * @Version: v0.1
 * @param <T>
 */  
public interface Pagination<T> {
    /**
     * 判断是否是首页
     * @return
     */
    boolean isFirst();
    /**
     * 判断是否是尾页
     * @return
     */
    boolean isLast();
    /**
     * 判断是否有上一页
     * @return
     */
    boolean isPrevious();
    /**
     * 判断是否有下一页
     * @return
     */
    boolean isNext();


    /**
     * 获取上一页的页码
     * @return
     */
    int getPreviousIndex();
    /**
     * 获取下一页的页码
     * @return
     */
    int getNextIndex();
    /**
     * 获取当前页码
     * @return
     */
    int getPageIndex();
    /**
     * 获取当前页大小
     * @return
     */
    int getPageSize();
    /**
     * 获取总页数
     * @return
     */
    int getTotalPages();
    /**
     * 获取数据总行数
     * @return
     */
    int getTotalElements();

    /**
     * 获取当前页的数据
     * @return
     */
    List<T> getCurrData();

    /**
     * 获取数字分页链接对象
     * @return
     */
    BetweenIndex getBetweenIndex();

    /**
     * 获取每页显示的分页链接数
     * @return
     */
    int getPageLinkNumber();

    /**
     * 设置每页的分页链接数量
     * @param pageLinkNumber
     */
    void setPageLinkNumber(int pageLinkNumber);
}

BetweenIndex.java (interface)

该接口负责获取分页链接的开始和结尾索引
包名: com.app.pagination;

package com.app.pagination;
/**
 * 开始链接-结束链接
 * @author: wuwz@live.com
 * @ClassName: BetweenIndex
 * @Version: v0.1
 */
public interface BetweenIndex {
    /**
     * 获取开始分页链接索引
     * @return
     */
    int getBeginIndex();
    /**
     * 获取结束分页链接索引
     * @return
     */
    int getEndIndex();
}

DefaultPagination.java (implements Pagination)

Pagination接口的默认实现类
包名: com.app.pagination.impl;

package com.app.pagination.impl;
import java.util.List;
import com.app.pagination.BetweenIndex;
import com.app.pagination.Pagination;
/**
 * Pagination接口默认实现
 * @author: wuwz@live.com
 * @ClassName: DefaultPagination
 * @Version: v0.1
 * @param <T>
 */
public class DefaultPagination<T> implements Pagination<T> {
    private int totalElements;
    private int pageSize;
    private int totalPages;
    private int pageIndex;
    private QueryHandler<T> queryHandler;
    private List<T> currData;
    private int pageLinkNumber;

    public DefaultPagination(int pageIndex, int pageSize, QueryHandler<T> queryHandler, int pageLinkNumber) {
        this(pageIndex, pageSize, queryHandler);
        setPageLinkNumber(pageLinkNumber);
    }
    public DefaultPagination(int pageIndex, int pageSize, QueryHandler<T> queryHandler){
        //初始化数据访问回调接口
        this.queryHandler = queryHandler;
        //查询总行数
        setTotalElements();
        //修正页大小
        setPageSize(pageSize);
        //计算总页数:
        setTotalPages();
        //修正页码
        setPageIndex(pageIndex);
        //查询当前页数据
        setCurrData();
    }


    private void setCurrData() {

        this.currData = queryHandler.getCurrData(pageIndex, pageSize);
    }
    private void setPageIndex(int pageIndex) {

        if(pageIndex < 1) {
            this.pageIndex  = 1;
        } else if(pageIndex > totalPages) {
            this.pageIndex = totalPages;
        } else {
            this.pageIndex = pageIndex;
        }
    }
    private void setTotalPages() {

        if(pageSize > 0) {
            /*//普通算法: 
            this.totalPages = totalElements % pageSize == 0 ? 
                    totalElements / pageSize : (totalElements / pageSize) + 1;*/
            //减一公式:
            this.totalPages = (totalElements + pageSize - 1) / pageSize;
        }
    }
    private void setPageSize(int pageSize) {

        if(pageSize < 1) {
            this.pageSize = 1;
        } else if(pageSize > totalElements) {
            this.pageSize = totalElements;
        } else {
            this.pageSize = pageSize;
        }
    }
    private void setTotalElements() {

        this.totalElements = queryHandler.getTotalElements();
    }
    @Override
    public boolean isFirst() {

        return pageIndex == 1;
    }
    @Override
    public boolean isLast() {

        return pageIndex == totalPages;
    }
    @Override
    public boolean isPrevious() {

        return pageIndex > 1;
    }
    @Override
    public boolean isNext() {

        return pageIndex < totalPages;
    }
    @Override
    public int getPreviousIndex() {

        return isPrevious() ? pageIndex - 1 : 1;
    }
    @Override
    public int getNextIndex() {

        return isNext() ? pageIndex + 1 : totalPages;
    }
    @Override
    public int getPageIndex() {

        return pageIndex;
    }
    @Override
    public int getPageSize() {

        return pageSize;
    }
    @Override
    public int getTotalPages() {

        return totalPages;
    }
    @Override
    public int getTotalElements() {

        return totalElements;
    }
    @Override
    public List<T> getCurrData() {

        return currData;
    }
    @Override
    public BetweenIndex getBetweenIndex() {

        return new BetweenIndex() {
            private int beginIndex;
            private int endIndex;

            {
                boolean isOdd = pageLinkNumber % 2 == 0;
                int val = pageLinkNumber / 2;
                beginIndex = pageIndex - (isOdd ? val - 1: val);
                endIndex = pageIndex + val;

                if(beginIndex < 1) {
                    beginIndex  = 1;
                    endIndex = pageLinkNumber;
                }
                if(endIndex > totalPages) {
                    endIndex = totalPages;
                    beginIndex = endIndex - pageLinkNumber + 1;
                }
            }
            @Override
            public int getEndIndex() {

                return endIndex;
            }

            @Override
            public int getBeginIndex() {

                return beginIndex;
            }
        };
    }
    @Override
    public int getPageLinkNumber() {

        return pageLinkNumber;
    }
    @Override
    public void setPageLinkNumber(int pageLinkNumber) {

        if (pageLinkNumber < 0) {
            this.pageLinkNumber = 0;
        } else if (pageLinkNumber > totalPages) {
            this.pageLinkNumber = totalPages;
        } else {
            this.pageLinkNumber = pageLinkNumber;
        }
    }
}

QueryHandler.java(interface)

用于DefaultPagination实现类的查询回调接口
包名: com.app.pagination.impl;

package com.app.pagination.impl;
import java.util.List;
/**
 * 分页查询回调接口
 * @author: wuwz@live.com
 * @ClassName: QueryHandler
 * @Version: v0.1
 * @param <T>
 */
public interface QueryHandler<T> {
    /**
     * 获取数据总行数
     * @return
     */
    int getTotalElements();

    /**
     * 获取当前页的数据
     * @param pageIndex
     * @param pageSize
     * @return
     */
    List<T> getCurrData(int pageIndex, int pageSize);
}

BookDaoImpl.java (implements BookDao)

BookDao的实现类(BookDao接口已经省略)
包名: com.app.dao.impl;

package com.app.dao.impl;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import com.app.bean.Book;
import com.app.dao.BaseDao;
import com.app.dao.BookDao;
public class BookDaoImpl extends BaseDao implements BookDao {
    @Override
    public int count() {
        // 查询数据总行数
        String sql = "select count(1) from t_book";
        try {
            return getQueryRunner().query(sql, new ScalarHandler<Integer>());
        } catch (SQLException e) {

            e.printStackTrace();
        }
        return 0;
    }
    @Override
    public List<Book> getBooks(int pageIndex, int pageSize) {
        // 关于SQLServer的查询分页sql
        StringBuffer sql = new StringBuffer();
        sql.append("select * from (");
        sql.append("    select row_number() over(order by(id)) new_id,* from t_book");
        sql.append(") t where new_id between ? and ?");
        try {
            return getQueryRunner().query(sql.toString(),
                    new BeanListHandler<Book>(Book.class), 
                        pageSize * (pageIndex - 1) + 1,pageSize * pageIndex);
        } catch (SQLException e) {

            e.printStackTrace();
        }
        return null;
    }
}

BookServiceImpl.java (implements BookService)

BookService业务逻辑接口的实现类 (BookService已经省略)
包名: com.app.service.impl;

package com.app.service.impl;
import java.util.List;
import com.app.bean.Book;
import com.app.dao.BookDao;
import com.app.dao.impl.BookDaoImpl;
import com.app.pagination.Pagination;
import com.app.pagination.impl.DefaultPagination;
import com.app.pagination.impl.QueryHandler;
import com.app.service.BookService;
/**
 * 业务逻辑层查询分页数据示例
 * @author: wuwz@live.com
 * @ClassName: BookServiceImpl
 * @Version: v0.1
 */
public class BookServiceImpl implements BookService {

    private BookDao bookDao = new BookDaoImpl();

    @Override
    public Pagination<Book> getBookList(int pageIndex, int pageSize,int pageLinkNumber) {

        return new DefaultPagination<Book>(pageIndex, pageSize, new QueryHandler<Book>() {
            @Override
            public int getTotalElements() {

                return bookDao.count();
            }
            @Override
            public List<Book> getCurrData(int pageIndex, int pageSize) {

                return bookDao.getBooks(pageIndex, pageSize);
            }
        },pageLinkNumber);
    }
}

BookAction.java (Servlet)

有关图书的Servlet控制器
包名: com.app.web.action;

package com.app.web.action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.app.bean.Book;
import com.app.pagination.Pagination;
import com.app.service.BookService;
import com.app.service.impl.BookServiceImpl;
public class BookAction extends HttpServlet {
    private static final long serialVersionUID = 5275929408058702210L;
    private BookService bookService = new BookServiceImpl();

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        int pageIndex = 1;
        int pageSize = 10;
        try {
            pageIndex = Integer.parseInt(request.getParameter("pageIndex"));
            pageSize = Integer.parseInt(request.getParameter("pageSize"));
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
         //6: 显示的分页链接个数
        Pagination<Book> bookPagination = bookService.getBookList(pageIndex, pageSize,6);
        request.setAttribute("bookPagination", bookPagination);
        request.getRequestDispatcher("index.jsp").forward(request, response);
    }
}

index.jsp

将Pagiation应用到bootstrap上的简单示例
bootstrap版本: 3.3.5

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:if test="${requestScope.bookPagination == null }">
    <c:redirect url="bookAction?pageIndex=1&pageSize=4"></c:redirect>
</c:if>
<!DOCTYPE html">
<html>
  <head>
      <title>图书信息列表</title>
      <!-- Bootstrap v3.3.5 -->
<link href="${pageContext.request.contextPath}/bootstrap-3.3.5-dist/css/bootstrap.min.css"
    type="text/css" rel="stylesheet" charset="utf-8" />
<link id="bootstrapTheme"
    href="${pageContext.request.contextPath}/bootstrap-3.3.5-dist/css/bootstrap-theme.min.css"
    type="text/css" rel="stylesheet" charset="utf-8" />
<script src="${pageContext.request.contextPath}/bootstrap-3.3.5-dist/js/jquery.min.js"
    type="text/javascript" charset="utf-8"></script>
<script src="${pageContext.request.contextPath}/bootstrap-3.3.5-dist/js/bootstrap.min.js"
    type="text/javascript" charset="utf-8"></script>
  </head>
  <body>
  <div class="container">
      <h2 class="page-header">图书信息</h2>
      <table class="table table-striped table-bordered table-hover">
          <tr>
              <th>#</th>
              <th>图书名</th>
              <th>单价</th>
          </tr>
          <c:set var="bookPagination" value="${requestScope.bookPagination}"></c:set>
          <c:choose>
              <c:when test="${bookPagination.totalElements gt 0}">
                  <c:forEach var="book" items="${bookPagination.currData}">
                      <tr>
                          <td>${book.id }</td>
                          <td>${book.name }</td>
                          <td>${book.price }</td>
                      </tr>
                  </c:forEach>

                  <td colspan="3" align="center">
                  <div class="btn-group" role="group">
                      <c:if test="${bookPagination.first}" var="isFirst">
                          <a class="btn btn-primary btn-sm" disabled="disabled" href="#">首页</a> 
                          <a class="btn btn-success btn-sm" disabled="disabled" href="#">上一页</a>
                      </c:if>
                      <c:if test="${not isFirst}">
                        <a class="btn btn-primary btn-sm" href="${pageContext.request.contextPath}/bookAction?pageIndex=1&pageSize=${bookPagination.pageSize}">首页</a> 
                        <a class="btn btn-success btn-sm" href="${pageContext.request.contextPath}/bookAction?pageIndex=${bookPagination.previousIndex }&pageSize=${bookPagination.pageSize}">上一页</a>
                      </c:if>
                      <c:if test="${bookPagination.last }" var="isLast">
                          <a class="btn btn-success btn-sm" disabled="disabled" href="#">下一页</a> 
                          <a class="btn btn-primary btn-sm" disabled="disabled" href="#">尾页</a>
                      </c:if>
                      <c:if test="${not isLast}">
                        <a class="btn btn-success btn-sm" href="${pageContext.request.contextPath}/bookAction?pageIndex=${bookPagination.nextIndex }&pageSize=${bookPagination.pageSize}">下一页</a> 
                        <a class="btn btn-primary btn-sm" href="${pageContext.request.contextPath}/bookAction?pageIndex=${bookPagination.totalPages }&pageSize=${bookPagination.pageSize}">尾页</a>
                      </c:if>
                      </div>
                  </td>
              </c:when>
              <c:otherwise>
                  <tr><td colspan="3">没有更多数据!</td></tr>
              </c:otherwise>
          </c:choose>
      </table>
      <center>
          <nav>
          <ul class="pagination">
          <c:if test="${isFirst }">
               <li class="disabled">
                  <a href="#" aria-label="Previous">
                    <span aria-hidden="true">»上一页</span>
                  </a>
                </li>
            </c:if>
            <c:if test="${not isFirst }">
                <li>
                  <a href="${pageContext.request.contextPath}/bookAction?pageIndex=${bookPagination.previousIndex }&pageSize=${bookPagination.pageSize}" aria-label="Previous">
                    <span aria-hidden="true">»上一页</span>
                  </a>
                </li>
            </c:if>
            <c:if test="${bookPagination.pageLinkNumber gt 0}">
                <c:set var="betweenIndex" value="${bookPagination.betweenIndex}"></c:set>
                <c:forEach var="linkIndex" begin="${betweenIndex.beginIndex}" end="${betweenIndex.endIndex}">
                    <c:if test="${linkIndex eq  bookPagination.pageIndex}" var="isCurr">
                        <li class="active"><a href="#">${linkIndex}</a></li>
                    </c:if>
                    <c:if test="${not isCurr}">
                        <li><a href="${pageContext.request.contextPath}/bookAction?pageIndex=${linkIndex}&pageSize=${bookPagination.pageSize}" >${linkIndex}</a></li>
                    </c:if>
                </c:forEach>
            </c:if>
            <c:if test="${isLast }">
               <li class="disabled">
                  <a href="#" aria-label="Next">
                    <span aria-hidden="true">下一页 »</span>
                  </a>
                </li>
            </c:if>
            <c:if test="${not isLast }">
                <li>
                  <a href="${pageContext.request.contextPath}/bookAction?pageIndex=${bookPagination.nextIndex }&pageSize=${bookPagination.pageSize}" aria-label="Next">
                    <span aria-hidden="true">下一页 »</span>
                  </a>
                </li>
            </c:if>
          </ul>
        </nav>
      </center>
  </div>
  </body>
</html> 

运行示例:

这里写图片描述

说明:

  1. 如果需要扩展分页功能, 请扩展Pagiation接口以及其余实现类;
  2. 此外, 此分页不依赖任何数据库(重新实现QueryHandler查询回调接口即可), 可适用于任何web项目中;

使用List集合模拟数据库的使用示例:

package com.app.service.impl;
import java.util.ArrayList;
import java.util.List;
import com.app.bean.Book;
import com.app.pagination.Pagination;
import com.app.pagination.impl.DefaultPagination;
import com.app.service.BookService;
/**
 * 使用List<T>集合模拟数据库
 * @author: wuwz@live.com
 * @ClassName: BookServiceImpl2
 * @Version: v0.1
 */
public class BookServiceImpl2 implements BookService {
//    private BookDao bookDao = new BookDaoImpl();
    private static List<Book> list = new ArrayList<Book>();
    //初始化List<Book>数据
    static {
        list.add(new Book(1, "书名1", 18));
        list.add(new Book(2, "书名2", 13));
        list.add(new Book(3, "书名3", 18));
        list.add(new Book(4, "书名4", 38));
        list.add(new Book(5, "书名5", 18));
        list.add(new Book(6, "书名6", 58));
        list.add(new Book(7, "书名7", 12));
        list.add(new Book(8, "书名8", 11));
        list.add(new Book(9, "书名9", 13));
        list.add(new Book(10, "书名10", 22));
        list.add(new Book(11, "书名11", 19));
        list.add(new Book(12, "书名12", 13));
        list.add(new Book(13, "书名13", 19));
        list.add(new Book(14, "书名14", 32));
    }
    @Override
    public Pagination<Book> getBookList(int pageIndex, int pageSize, int pageLinkNumber) {
        return new DefaultPagination<Book>(pageIndex, pageSize, new QueryHandler<Book>() {
            @Override
            public int getTotalElements() {
                  //return bookDao.count();
                return list.size();
            }
            @Override
            public List<Book> getCurrData(int pageIndex, int pageSize) {
                  //return bookDao.list(pageIndex, pageSize);
                int fromIndex = (pageIndex - 1) * pageSize;
                int endIndex = fromIndex + pageSize;
                endIndex = endIndex > list.size() ? list.size() : endIndex;
                return list.subList(fromIndex, endIndex);
            }
        }, pageLinkNumber);
    }
}
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。