zoukankan      html  css  js  c++  java
  • 数据量你造吗-JAVA分页

    原创地址:   http://www.cnblogs.com/Alandre/  (泥沙砖瓦浆木匠),需要转载的,保留下! Thanks  

        学习的心态第一,解行要相应。其实《弟子规》在“余力学文”当中,一开头就强调了这一个重点。“不力行,但学文,长浮华,成何人”,这个没有侥幸的,只要学了不去做,无形当中就会增长傲慢,自己不知道。-<弟子规>

    Written In The Font

        JAVA-Web 基础那块,我自己也准备.搞哪里,优化哪里然后带给大家终结.谢谢

        分页虽易,好却难.数据量,怎么办?

    Content

        分页(Paging),就像个切面.能把这个切面好好的放进去也是种nice方式.

    第一种:小数据量分页实现 (可广泛用于 门户型 网页快速开发等)


        这种比较简单,这边我们模拟实现.

        字段结构:

                       private int pageSize; //每页有多少条

                       private int rowCount; //总行数  

                       private int pageCount;//总页数

                       private int currentPage; //当前页码

       

        流程结构:               

                     YTAY2KI}9BXPN(~3EA9BI6D

         核心:
                list.subList(index, (currentPage < pageCount) ? (index + pageSize) : rowCount);将小数据量集合,根据分页参数返回指定的list部分.这样,如果数据小的话,这样很方便的实现了分页功能.下面是JDK api里面对方法的解释:

    subList(int fromIndex, int toIndex)
              返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

    分页工具类:

    package jeffli_10;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /** 分页类:根据总记录数和分页大小对 {@link List} 进行分页处理 */
    public class Pagination
    {
        public static final int DEFAULT_PAGE_SIZE = 10;
        
        private int rowCount;
        private int currentPage;
        private int pageSize;
        private int pageCount;
        
        private List<?> list;
        
        public Pagination(List<?> list)
        {
            this(list, DEFAULT_PAGE_SIZE);
        }
        
        public Pagination(List<?> list, int pageSize)
        {
            this.currentPage    = 1;
            this.list            = list;
            this.rowCount        = list.size();
            
            setPageSize(pageSize);
        }
        
        private void adjustPageCount()
        {
            pageCount = (rowCount + pageSize - 1) / pageSize;
        }
        
        /** 获取要分页的 {@link List}  */
        public List<?> getList()
        {
            return list;
        }
        
        /** 获取的 {@link List} 当前页内容 */
        public List<?> getCurrentList()
        {
            List<?> currentList = null;
            
            if(currentPage >= 1 && currentPage <= pageCount)
            {
                int index = (currentPage - 1) * pageSize;
                currentList = list.subList(index, (currentPage < pageCount) ? (index + pageSize) : rowCount);
            }
    
            return currentList;
        }
        
    
        /** 获取当前页号(从 1 开始) */
        public int getCurrentPage()
        {
            return currentPage;
        }
    
        /** 设置当前页号(从 1 开始) */
        public boolean setCurrentPage(int page)
        {
            if(page >= 1 && page <= pageCount)
            {
                currentPage = page;
                return true;
            }
            
            return false;
        }
        
        /** 转到下一页 */
        public boolean nextPage()
        {
            return setCurrentPage(currentPage + 1);
        }
    
        /** 转到上一页 */
        public boolean prePage()
        {
            return setCurrentPage(currentPage - 1);
        }
    
        /** 获取分页大小 */
        public int getPageSize()
        {
            return pageSize;
        }
    
        /** 设置分页大小 */
        public void setPageSize(int size)
        {
            if(size <= 0)
                size = DEFAULT_PAGE_SIZE;
            
            int index = (currentPage - 1) * pageSize;
            
            pageSize = size;
                    
            if(index > pageSize)
                currentPage = (index + pageSize - 1) / pageSize;
            else
                currentPage = 1;
        
            adjustPageCount();
        }
    
        /** 获取总页数 */
        public int getPageCount()
        {
            return pageCount;
        }
        
        
        public static void main(String[] args)
        {
            final int PAGE_SIZE        = 10;
            final int LIST_SIZE        = 39;
            
            List<Integer> list = new ArrayList<Integer>();
            for(int i = 1; i <= LIST_SIZE; i++)
                list.add(i);
            
            Pagination pg = new Pagination(list, PAGE_SIZE);
            
            for(int i = 1; i <= pg.getPageCount(); i++)
            {
                    pg.setCurrentPage(i);
                    System.out.println(pg.getCurrentList());
            }
        }
        
    }

    RUN,你会看到 OUTPUTS:

    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
    [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
    [31, 32, 33, 34, 35, 36, 37, 38, 39]

    第二种:大数据量,采取DAO层分页操作(普遍性需求)


    环境:

            spring MVC (spring-4.0.0.RELEASE.jar)

            hibernate     (hibernate-core-4.3.5.Final.jar)

            Mysql           

    两个核心工具类-分页

    分页对象,包含所需要的所有参数及逻辑.

    package sedion.jeffli.wmuitp.util;
    
    
    import java.util.List;
    
    import org.apache.commons.lang3.StringUtils;
    
    import com.google.common.collect.Lists;
    
    public class Page<T> {
    
        //public variables 
        public static final String ASC     = "asc";
        public static final String DESC = "desc";
    
        //parameters of page
        protected int pageNo         = 1;
        protected int pageSize         = -1;
        
        protected String orderBy     = null;
        protected String order         = null;
        
        protected boolean autoCount = true;
    
        //results
        protected long totalCount     = -1;
        protected List<T> result     = Lists.newArrayList();
    
        public Page() 
        {
            
        }
    
        public Page(int pageSize) 
        {
            this.pageSize = pageSize;
        }
    
        /**
         * 获得当前页的页号,序号从1开始,默认为1.
         */
        public int getPageNo() 
        {
            return pageNo;
        }
    
        /**
         * 设置当前页的页号,序号从1开始,低于1时自动调整为1.
         */
        public void setPageNo(final int pageNo) 
        {
            this.pageNo = pageNo;
    
            if (pageNo < 1) 
                this.pageNo = 1;
        }
    
        /**
         * 返回Page对象自身的setPageNo函数,可用于连续设置。
         */
        public Page<T> pageNo(final int thePageNo) 
        {
            setPageNo(thePageNo);
            return this;
        }
    
        /**
         * 获得每页的记录数量, 默认为-1.
         */
        public int getPageSize() 
        {
            return pageSize;
        }
    
        /**
         * 设置每页的记录数量.
         */
        public void setPageSize(final int pageSize) 
        {
            this.pageSize = pageSize;
        }
    
        /**
         * 返回Page对象自身的setPageSize函数,可用于连续设置。
         */
        public Page<T> pageSize(final int thePageSize) 
        {
            setPageSize(thePageSize);
            return this;
        }
    
        /**
         * 根据pageNo和pageSize计算当前页第一条记录在总结果集中的位置,序号从1开始.
         */
        public int getFirst() 
        {
            return ((pageNo - 1) * pageSize) + 1;
        }
    
        /**
         * 获得排序字段,无默认值. 多个排序字段时用','分隔.
         */
        public String getOrderBy() 
        {
            return orderBy;
        }
    
        /**
         * 设置排序字段,多个排序字段时用','分隔.
         */
        public void setOrderBy(final String orderBy) 
        {
            this.orderBy = orderBy;
        }
    
        /**
         * 返回Page对象自身的setOrderBy函数,可用于连续设置。
         */
        public Page<T> orderBy(final String theOrderBy) 
        {
            setOrderBy(theOrderBy);
            return this;
        }
    
        /**
         * 获得排序方向, 无默认值.
         */
        public String getOrder() 
        {
            return order;
        }
    
        /**
         * 设置排序方式向.
         * 
         * @param order
         *            可选值为desc或asc,多个排序字段时用','分隔.
         */
        public void setOrder(final String order) 
        {
            String lowcaseOrder = StringUtils.lowerCase(order);
    
            String[] orders = StringUtils.split(lowcaseOrder, ',');
            for (String orderStr : orders) {
                if (!StringUtils.equals(DESC, orderStr) && !StringUtils.equals(ASC, orderStr)) {// 检查order字符串的合法值
                    throw new IllegalArgumentException("排序方向" + orderStr + "不是合法值");
                }
            }
    
            this.order = lowcaseOrder;
        }
    
        /**
         * 返回Page对象自身的setOrder函数,可用于连续设置。
         */
        public Page<T> order(final String theOrder) 
        {
            setOrder(theOrder);
            return this;
        }
    
        /**
         * 是否已设置排序字段,无默认值.
         */
        public boolean isOrderBySetted() 
        {
            return (StringUtils.isNotBlank(orderBy) && StringUtils.isNotBlank(order));
        }
    
        /**
         * 获得查询对象时是否先自动执行count查询获取总记录数, 默认为false.
         */
        public boolean isAutoCount() 
        {
            return autoCount;
        }
    
        /**
         * 设置查询对象时是否自动先执行count查询获取总记录数.
         */
        public void setAutoCount(final boolean autoCount) 
        {
            this.autoCount = autoCount;
        }
    
        /**
         * 返回Page对象自身的setAutoCount函数,可用于连续设置。
         */
        public Page<T> autoCount(final boolean theAutoCount) 
        {
            setAutoCount(theAutoCount);
            return this;
        }
    
        // -- 访问查询结果函数 --//
    
        /**
         * 获得页内的记录列表.
         */
        public List<T> getResult() 
        {
            return result;
        }
    
        /**
         * 设置页内的记录列表.
         */
        public void setResult(final List<T> result) 
        {
            this.result = result;
        }
    
        /**
         * 获得总记录数, 默认值为-1.
         */
        public long getTotalCount() 
        {
            return totalCount;
        }
    
        /**
         * 设置总记录数.
         */
        public void setTotalCount(final long totalCount) 
        {
            this.totalCount = totalCount;
        }
    
        /**
         * 根据pageSize与totalCount计算总页数, 默认值为-1.
         */
        public long getTotalPages() 
        {
            if (totalCount < 0) 
                return 1;
            
            long count = totalCount / pageSize;
            
            if (totalCount % pageSize > 0) 
                count++;
            return count;
        }
    
        /**
         * 是否还有下一页.
         */
        public boolean isHasNext()
        {
            return (pageNo + 1 <= getTotalPages());
        }
    
        /**
         * 取得下页的页号, 序号从1开始. 当前页为尾页时仍返回尾页序号.
         */
        public int getNextPage() 
        {
            if (isHasNext())
                return pageNo + 1;
            else 
                return pageNo;
        }
    
        /**
         * 是否还有上一页.
         */
        public boolean isHasPre() 
        {
            return (pageNo - 1 >= 1);
        }
    
        /**
         * 取得上页的页号, 序号从1开始. 当前页为首页时返回首页序号.
         */
        public int getPrePage() 
        {
            if (isHasPre()) 
                return pageNo - 1;
            else 
                return pageNo;
        }
    
        public long getBegin() 
        {
            return Math.max(1, getPageNo() - pageSize / 2);
        }
    
        public long getEnd() 
        {
            return getTotalPages();
        }
    }

    分页初始化(包括参数变化)

    package sedion.jeffli.wmuitp.util;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.lang3.StringUtils;
    
    import com.sun.org.apache.xml.internal.resolver.helpers.PublicId;
    
    import sedion.jeffli.wmuitp.entity.SubjectInfor;
    
    /**
     * 分页工具
     * 
     */
    public class PageUtil {
    
        public static int PAGE_SIZE             = 20;
        public static int MAX_SIZE              = 9999;
        
        public static final String PAGE_NUM_STR = "pageNum";
        
        /**
         * 初始化分页
         * @param page        page对象
         * @param request     请求体
         * @return
         */
        public static int[] init(Page<?> page, HttpServletRequest request) {
            
            int pageNum = Integer.parseInt(StringUtils.defaultIfBlank(request.getParameter(PAGE_NUM_STR), "1"));
            
            page.setPageNo(Integer.valueOf(pageNum));
            page.setPageSize(page.getPageSize());
            
            int firstResult = page.getFirst() - 1;
            int maxResults = page.getPageSize();
            
            return new int[] { firstResult, maxResults };
        }
    }

    #这里我们用request.getParameter(PAGE_NUM_STR) 获取分页操作时改变的字段.这样不必要每次都在Controller上附带参数了.

    页面端:

        <form id="pagerForm" method="post" action="${ctx}/subjectInfor/subjectInfors">
            <input type="hidden" name="pageNum"     value=${page.getPageNo()} />
            <input type="hidden" name="numPerPage"     value=${page.getPageSize()} />
        </form>
        <div class="panelBar">
            <div class="pages">
                <span>显示</span>
                <select class="combox" name="numPerPage" onchange="navTabPageBreak({numPerPage:this.value})">
                    <option value="20"     <#if numPerPage == 20>    selected</#if>>20    </option>
                    <option value="50"     <#if numPerPage == 50>    selected</#if>>50    </option>
                    <option value="100" <#if numPerPage == 100>    selected</#if>>100    </option>
                    <option value="200" <#if numPerPage == 200>    selected</#if>>200    </option>
                </select>
                <span>条,共${page.getTotalCount()}条</span>
            </div>
        <div class="pagination" totalCount=${page.getTotalCount()} numPerPage=${page.getPageSize()} pageNumShown="10" currentPage=${page.getPageNo()}></div>

    然后到Controller层:

    @RequestMapping(value = "/subjectInfors")
        public ModelAndView subjectInfos()
        {    
            ModelAndView mav = new ModelAndView(SubjectInforWebConstant.getSubjectInforListView());
            
            try {
                
                Page<SubjectInfor> page = new Page<>(PageUtil.PAGE_SIZE);
                int[] pageParams = PageUtil.init(page,request);//分页初始化
                subjectInforService.getSubjectInforsPages(page, pageParams);
                
                mav.addObject(MainWebConstant.getPage(), page);
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            return mav;
        }

    调用Service层:

    @Override
        public List<SubjectInfor> getSubjectInforsPages(Page<SubjectInfor> page, int[] pageParams)
        {
            List<SubjectInfor> results = new ArrayList<>();
    
            StringBuffer resultsHQL = new StringBuffer(All_SUBJECT_INFORS);
            
            try
            {
                results = subjectInforDAO.findByPage(resultsHQL.toString(), pageParams[0], pageParams[1]);
                
                page.setTotalCount(subjectInforDAO.getCount(resultsHQL.toString()));
                page.setResult(results);
                
            } catch (Exception e)
            {
                e.printStackTrace();
            }
            
    
            return results;
        }

    调用DAO层:

       /**
         * find entity-s of database by hql
         * --------------------------------------------------------
         * @param(String)     hql            
         * @param(String)     offset        当前标识    
         * @param(String)     pageSize    分页大小
         * @return            null/List<T>
         */
        @SuppressWarnings("unchecked")
        public List<T> findByPage(String hql, int offset, int pageSize) 
        {
            if (hql == null) 
            {
                return new ArrayList<T>();
            }
            Query query = createQuery(hql);
            if (!(offset == 0 && pageSize == 0)) 
            {
                query.setFirstResult(offset).setMaxResults(pageSize);
            }
            if (query.list() != null)
                return query.list();
            else
                return null;
    
        }

    实现的效果图:

    image

    #这样分页就简简单单实现了.

    Editor's Note

                 找我加群,一起共勉!

    QQ截图20140525001523_thumb[3]

  • 相关阅读:
    Kafka~Linux环境下的部署
    Zookeeper~Linux环境下的部署
    pwd显示链接文件的真实路径
    3种不同方式的焦点图轮播
    软件集成策略——如何有效率地提升质量
    寻找直方图中面积最大的矩形 --- 庞果网
    再谈线程
    SQL 常用基础语句
    初识Maven
    公司存在的问题
  • 原文地址:https://www.cnblogs.com/Alandre/p/3762599.html
Copyright © 2011-2022 走看看