【小轮子】自制分页组件小结          返回主页

近来开发强度逐渐增加,在写代码的过程中遇到的重复逻辑越来越多,作为一个有进取心的猴子怎么能够忍受代码的坏味道呢?于是就想写一个小的分页组件,将重复的公共代码抽离出来打包为jar引入项目中调用。这样能够大大的减少重复劳动,也能锻炼自己的造轮子的能力。

分页最主要的是对页面的实体的定义,一个分页实体中包含如下属性

分页得到的记录列表 由数据访问层获得
当前页码 由前台控制器传入
总记录数 由数据访问层获得
页大小 暂时手动指定为每页10个
总的页数 计算公式:记录数除以页大小,如果能整除则为商,否则为结果加1
每一页开始记录 计算公式:(当前页码-1)*每页大小
查询分页请求url 由控制器通过set方法注入

根据上述要求我定义了这样的Page实体

        public class Page {
            //分页记录Dao查出
            @SuppressWarnings("rawtypes")
            private List Records;
            //当前页码
            private int currentPageNum;
            //总记录数
            private int totalRecords;
            //页大小
            private int pageSize = 8;
            //总的页数
            private int totalPage;
            //每一页开始记录
            private int startIndex;
            //开始页码
            private int startPage;
            //结束页码
            private int endPage;
            //查询分页请求url
            private String url;
            ..省略get set

            public Page(int currentPageNum, int totalRecords ) {
                this.currentPageNum = currentPageNum;
                this.totalRecords = totalRecords;
                //计算总页数
                totalPage = (totalRecords % pageSize == 0) ?
                                    totalRecords/pageSize : (totalRecords / pageSize + 1);
                //开始索引
                startIndex = (currentPageNum - 1) * pageSize;

                //计算开始和结束页码
                if(totalPage<=5){//不足9页
                    startPage = 1;
                    endPage = totalPage;
                }else{
                    startPage = currentPageNum-4;
                    endPage = currentPageNum+4;
                    if(startPage<1){
                        startPage = 1;
                        endPage = startPage+8;
                    }
                    if(endPage>totalPage){
                        endPage = totalPage;
                        startPage = endPage-8;
                    }
                }
            }
        }

这里通过构造方法将属性计算出来然后构造出Page实体

分页服务接口

    /**
     * 分页服务获取Page实体
     * @author Administrator
     * 实现该接口即可获取Page实体
     *
     */
    public interface PageService {
        //获取分页bean
        Page findPageRecords(String num);
    }

分页服务接口实现

    public class PageServiceImpl implements PageService {

        public PageServiceImpl(PageDAO pageDAO) {
            this.pageDAO = pageDAO;
        }

        public PageServiceImpl() {
            super();
        }

        @Override
        public Page findPageRecords(String num) {
            int pageNum = 1;
            if (num != null && !num.trim().equals("")) {
                pageNum = Integer.valueOf(num);
            }
            if (pageNum <= 0) {
                pageNum = 1;
            }
            int totalRecords = pageDAO.fetchEntityRowsAccount();
            Page page = new Page(pageNum, totalRecords);
            //获取分页记录
            page.setRecords(pageDAO.findEntityRecords(page.getStartIndex(), page.getPageSize()));
            //当前页大于总页数设置当前页为总页数
            if (pageNum >= page.getEndPage() ) {
                page.setCurrentPageNum(page.getEndPage());
            }
            return page;
        }

    }

这里我定义了一个分页接口并实现了它,主要的方法为findPageRecords(String num),它接受当前的页码并返回Page实体,将分页的数据注入Page实体,并返回。

值得注意的是,PageServiceImpl的构造方法接受一个PageDAO的引用,这里的PageDAO是一个接口,用户需要实现这个接口并将引用注入构造方法中,这样在内部便能调用外部的持久层逻辑组装出Page,接下来我们便看看这个接口

PageDAO接口

public interface PageDAO{

    //获取实体总数
    public Integer fetchEntityRowsAccount();
    /**
     *
     * @param startIndex开始的索引
     * @param pageSize  每页大小
     * @return
     */
    @SuppressWarnings("rawtypes")
    public List findEntityRecords(Integer startIndex, Integer pageSize);

}

这里能够看出,用户需要实现这个接口的两个方法,用户可以自由选取合适的持久化框架去获取实体的总数以及查询每页实体的列表的逻辑。当前只兼容了Mysql的limit语法。

使用方法

那么如何使用呢?

很简单,只需要将此jar添加到classpath并实现PageDAO接口然后就可以在你的控制层中去调用了,这里我给出一个简单的例子,是servlet的调用方式,使用别的MVC框架调用会更简单。

//面向接口方式定义并实例化PageDAO接口

PageDAO pageDAO = new PageTestDAO();

//通过构造方式实例化PageService

PageService pageService = new PageServiceImpl(pageDAO);

//获取Page实例

Page page = pageService.findPageRecords(request.getParameter("num"));

page.setUrl("controller?num=");

//返回数据到前台遍历即可

request.setAttribute("page", page);

request.getRequestDispatcher("/WEB-INF/jsp/personList3.jsp").forward(request, response);

前台逻辑实现

                    <c:if test="${not empty requestScope.page}">
                    <ul class="pagination">
                            <li><a
                                href="${page.url}${requestScope.page.currentPageNum-1}"
                                aria-label="Previous"> <span aria-hidden="true">&laquo;</span>
                            </a></li>
                            <c:forEach begin="${page.startPage }" end="${page.endPage }"
                                var="num">
                                <li><a href="${page.url}${num}">${num}</a></li>
                            </c:forEach>
                            <li><a
                                href="${page.url}${requestScope.page.currentPageNum+1}"
                                aria-label="Next"> <span aria-hidden="true">&raquo;</span>
                            </a></li>
                        </ul>
                        <br/>
                        <li><button type="button" class="btn btn-primary"
                                onclick="window.location.href='${page.url}1'">
                                <span class="glyphicon glyphicon-home">首页</span></a>
                            </button></li>
                        <li><button type="button" class="btn btn-default"
                                onclick="window.location.href='${page.url}${requestScope.page.currentPageNum -1}'">
                                <span class="glyphicon glyphicon-circle-arrow-left">上一页</span>
                            </button></li>
                        <li><button type="button" class="btn btn-default"
                                onclick="window.location.href='controller?num=${requestScope.page.currentPageNum +1}'">
                                <span class="glyphicon glyphicon-circle-arrow-right">下一页</span>
                            </button></li>
                        <li><button type="button" class="btn btn-primary"
                                style="margin-right: 10px;"
                                onclick="window.location.href='${page.url}${requestScope.page.totalPage}'">
                                <span class="glyphicon glyphicon-play">尾页</span>
                            </button></li>

                        <li>当前${requestScope.page.currentPageNum }页</li>
                        <li>共${requestScope.page.totalPage}页</li>
                    </c:if>

这里使用JSTL标签将很方便的实现分页逻辑。不再赘述,项目的jar上传至我的github主页,欢迎尝试哦~