分页实现

  对于web应用来说分页显示数据是是最基本的功能,作为经常开发web应用的程序员来说这个功能也小菜一碟。闲着没事就把分页的实现写出来以便大家参考,不当之处欢迎批评指正。

1. 分页类(Page<T>

  1 import java.util.ArrayList;
  2 import java.util.List;
  3 import java.util.regex.Pattern;
  4 
  5 import javax.servlet.http.HttpServletRequest;
  6 import javax.servlet.http.HttpServletResponse;
  7 
  8 import org.apache.commons.lang3.StringUtils;
  9 
 10 import com.fasterxml.jackson.annotation.JsonIgnore;
 11 
 12 import com.common.utils.CookieUtils;
 13 
 14 /**
 15  * 分页类
 16  * @author libingbin
 17  * @version 1.0
 18  * @param <T>
 19  */
 20 public class Page<T> {
 21     
 22     protected int pageNo = 1; // 当前页码
 23     protected int pageSize = 15; // 页面大小,设置为“-1”表示不进行分页(分页无效)
 24     
 25     protected long count;// 总记录数,设置为“-1”表示不查询总数
 26     
 27     protected int first;// 首页索引
 28     protected int last;// 尾页索引
 29     protected int prev;// 上一页索引
 30     protected int next;// 下一页索引
 31     
 32     private boolean firstPage;//是否是第一页
 33     private boolean lastPage;//是否是最后一页
 34 
 35     protected int length = 8;// 显示页面长度
 36     protected int slider = 1;// 前后显示页面长度
 37     
 38     private List<T> list = new ArrayList<T>();
 39     
 40     private String orderBy = ""; // 标准查询有效, 实例: updatedate desc, name asc
 41 
 42     protected String funcName = "page"; // 设置点击页码调用的js函数名称,默认为page,在一页有多个分页对象时使用。
 43     
 44     protected String funcParam = ""; // 函数的附加参数,第三个参数值。
 45     
 46     private String message = ""; // 设置提示消息,显示在“共n条”之后
 47 
 48     public Page() {
 49         this.pageSize = -1;
 50     }
 51     
 52     /**
 53      * 构造方法
 54      * @param request 传递 repage 参数,来记住页码
 55      * @param response 用于设置 Cookie,记住页码
 56      */
 57     public Page(HttpServletRequest request, HttpServletResponse response){
 58         this(request, response, -2);
 59     }
 60 
 61     /**
 62      * 构造方法
 63      * @param request 传递 repage 参数,来记住页码
 64      * @param response 用于设置 Cookie,记住页码
 65      * @param defaultPageSize 默认分页大小,如果传递 -1 则为不分页,返回所有数据
 66      */
 67     public Page(HttpServletRequest request, HttpServletResponse response, int defaultPageSize){
 68         // 设置页码参数(传递repage参数,来记住页码)
 69         String no = request.getParameter("pageNo");
 70         if (StringUtils.isNumeric(no)){
 71             CookieUtils.setCookie(response, "pageNo", no);
 72             this.setPageNo(Integer.parseInt(no));
 73         }else if (request.getParameter("repage")!=null){
 74             no = CookieUtils.getCookie(request, "pageNo");
 75             if (StringUtils.isNumeric(no)){
 76                 this.setPageNo(Integer.parseInt(no));
 77             }
 78         }
 79         // 设置页面大小参数(传递repage参数,来记住页码大小)
 80         String size = request.getParameter("pageSize");
 81         if (StringUtils.isNumeric(size)){
 82             CookieUtils.setCookie(response, "pageSize", size);
 83             this.setPageSize(Integer.parseInt(size));
 84         }else if (request.getParameter("repage")!=null){
 85             no = CookieUtils.getCookie(request, "pageSize");
 86             if (StringUtils.isNumeric(size)){
 87                 this.setPageSize(Integer.parseInt(size));
 88             }
 89         }else if (defaultPageSize != -2){
 90             this.pageSize = defaultPageSize;
 91         }
 92         // 设置排序参数
 93         String orderBy = request.getParameter("orderBy");
 94         if (StringUtils.isNotBlank(orderBy)){
 95             this.setOrderBy(orderBy);
 96         }
 97     }
 98     
 99     /**
100      * 构造方法
101      * @param pageNo 当前页码
102      * @param pageSize 分页大小
103      */
104     public Page(int pageNo, int pageSize) {
105         this(pageNo, pageSize, 0);
106     }
107     
108     /**
109      * 构造方法
110      * @param pageNo 当前页码
111      * @param pageSize 分页大小
112      * @param count 数据条数
113      */
114     public Page(int pageNo, int pageSize, long count) {
115         this(pageNo, pageSize, count, new ArrayList<T>());
116     }
117     
118     /**
119      * 构造方法
120      * @param pageNo 当前页码
121      * @param pageSize 分页大小
122      * @param count 数据条数
123      * @param list 本页数据对象列表
124      */
125     public Page(int pageNo, int pageSize, long count, List<T> list) {
126         this.setCount(count);
127         this.setPageNo(pageNo);
128         this.pageSize = pageSize;
129         this.list = list;
130     }
131     
132     /**
133      * 初始化参数
134      */
135     public void initialize(){
136                 
137         //1
138         this.first = 1;
139         
140         this.last = (int)(count / (this.pageSize < 1 ? 20 : this.pageSize) + first - 1);
141         
142         if (this.count % this.pageSize != 0 || this.last == 0) {
143             this.last++;
144         }
145 
146         if (this.last < this.first) {
147             this.last = this.first;
148         }
149         
150         if (this.pageNo <= 1) {
151             this.pageNo = this.first;
152             this.firstPage=true;
153         }
154 
155         if (this.pageNo >= this.last) {
156             this.pageNo = this.last;
157             this.lastPage=true;
158         }
159 
160         if (this.pageNo < this.last - 1) {
161             this.next = this.pageNo + 1;
162         } else {
163             this.next = this.last;
164         }
165 
166         if (this.pageNo > 1) {
167             this.prev = this.pageNo - 1;
168         } else {
169             this.prev = this.first;
170         }
171         
172         //2
173         if (this.pageNo < this.first) {// 如果当前页小于首页
174             this.pageNo = this.first;
175         }
176 
177         if (this.pageNo > this.last) {// 如果当前页大于尾页
178             this.pageNo = this.last;
179         }
180         
181     }
182     
183     /**
184      * 默认输出当前分页标签 
185      * <div class="page">${page}</div>
186      */
187     @Override
188     public String toString() {
189 
190         StringBuilder sb = new StringBuilder();
191         sb.append("<div class=\"fixed-table-pagination\" style=\"display: block;\">");
192 
193         long startIndex = (pageNo-1)*pageSize + 1;
194         long endIndex = pageNo*pageSize <=count? pageNo*pageSize:count;
195         
196         sb.append("<div class=\"pull-left pagination-detail\">");
197         sb.append("<span class=\"pagination-info\">显示第 "+startIndex+" 到第 "+ endIndex +" 条记录,总共 "+count+" 条记录</span>");
198         sb.append("<span class=\"page-list\">每页显示 <span class=\"btn-group dropup\">");
199         sb.append("<button type=\"button\" class=\"btn btn-default  btn-outline dropdown-toggle\" data-toggle=\"dropdown\" aria-expanded=\"false\">");
200         sb.append("<span class=\"page-size\">"+pageSize+"</span> <span class=\"caret\"></span>");
201         sb.append("</button>");
202         sb.append("<ul class=\"dropdown-menu\" role=\"menu\">");
203         sb.append("<li class=\""+getSelected(pageSize,10)+ "\"><a href=\"javascript:"+funcName+"("+pageNo+",10,'"+funcParam+"');\">10</a></li>");
204         sb.append("<li class=\""+getSelected(pageSize,25)+ "\"><a href=\"javascript:"+funcName+"("+pageNo+",25,'"+funcParam+"');\">25</a></li>");
205         sb.append("<li class=\""+getSelected(pageSize,50)+ "\"><a href=\"javascript:"+funcName+"("+pageNo+",50,'"+funcParam+"');\">50</a></li>");
206         sb.append("<li class=\""+getSelected(pageSize,100)+ "\"><a href=\"javascript:"+funcName+"("+pageNo+",100,'"+funcParam+"');\">100</a></li>");
207         sb.append("</ul>");
208         sb.append("</span> 条记录</span>");
209         sb.append("</div>");
210 
211     
212         sb.append("<div class=\"pull-right pagination-roll\">");
213         sb.append("<ul class=\"pagination pagination-outline\">");
214         if (pageNo == first) {// 如果是首页
215             sb.append("<li class=\"paginate_button previous disabled\"><a href=\"javascript:\"><i class=\"fa fa-angle-double-left\"></i></a></li>\n");
216             sb.append("<li class=\"paginate_button previous disabled\"><a href=\"javascript:\"><i class=\"fa fa-angle-left\"></i></a></li>\n");
217         } else {
218             sb.append("<li class=\"paginate_button previous\"><a href=\"javascript:\" onclick=\""+funcName+"("+first+","+pageSize+",'"+funcParam+"');\"><i class=\"fa fa-angle-double-left\"></i></a></li>\n");
219             sb.append("<li class=\"paginate_button previous\"><a href=\"javascript:\" onclick=\""+funcName+"("+prev+","+pageSize+",'"+funcParam+"');\"><i class=\"fa fa-angle-left\"></i></a></li>\n");
220         }
221 
222         int begin = pageNo - (length / 2);
223 
224         if (begin < first) {
225             begin = first;
226         }
227 
228         int end = begin + length - 1;
229 
230         if (end >= last) {
231             end = last;
232             begin = end - length + 1;
233             if (begin < first) {
234                 begin = first;
235             }
236         }
237 
238         if (begin > first) {
239             int i = 0;
240             for (i = first; i < first + slider && i < begin; i++) {
241                 sb.append("<li class=\"paginate_button \"><a href=\"javascript:\" onclick=\""+funcName+"("+i+","+pageSize+",'"+funcParam+"');\">"
242                         + (i + 1 - first) + "</a></li>\n");
243             }
244             if (i < begin) {
245                 sb.append("<li class=\"paginate_button disabled\"><a href=\"javascript:\">...</a></li>\n");
246             }
247         }
248 
249         for (int i = begin; i <= end; i++) {
250             if (i == pageNo) {
251                 sb.append("<li class=\"paginate_button active\"><a href=\"javascript:\">" + (i + 1 - first)
252                         + "</a></li>\n");
253             } else {
254                 sb.append("<li class=\"paginate_button \"><a href=\"javascript:\" onclick=\""+funcName+"("+i+","+pageSize+",'"+funcParam+"');\">"
255                         + (i + 1 - first) + "</a></li>\n");
256             }
257         }
258 
259         if (last - end > slider) {
260             sb.append("<li class=\"paginate_button disabled\"><a href=\"javascript:\">...</a></li>\n");
261             end = last - slider;
262         }
263 
264         for (int i = end + 1; i <= last; i++) {
265             sb.append("<li class=\"paginate_button \"><a href=\"javascript:\" onclick=\""+funcName+"("+i+","+pageSize+",'"+funcParam+"');\">"
266                     + (i + 1 - first) + "</a></li>\n");
267         }
268 
269         if (pageNo == last) {
270             sb.append("<li class=\"paginate_button next disabled\"><a href=\"javascript:\"><i class=\"fa fa-angle-right\"></i></a></li>\n");
271             sb.append("<li class=\"paginate_button next disabled\"><a href=\"javascript:\"><i class=\"fa fa-angle-double-right\"></i></a></li>\n");
272         } else {
273             sb.append("<li class=\"paginate_button next\"><a href=\"javascript:\" onclick=\""+funcName+"("+next+","+pageSize+",'"+funcParam+"');\">"
274                     + "<i class=\"fa fa-angle-right\"></i></a></li>\n");
275             sb.append("<li class=\"paginate_button next\"><a href=\"javascript:\" onclick=\""+funcName+"("+last+","+pageSize+",'"+funcParam+"');\">"
276                     + "<i class=\"fa fa-angle-double-right\"></i></a></li>\n");
277         }
278 
279         
280         sb.append("</ul>");
281         sb.append("</div>");
282         sb.append("</div>");
283         
284         return sb.toString();
285     }
286     
287     protected String getSelected(int pageNo, int selectedPageNo){
288         if(pageNo == selectedPageNo){
289             //return "selected";
290             return "active";
291         }else{
292             return "";
293         }
294         
295     }
296     
297     /**
298      * 获取分页HTML代码
299      * @return
300      */
301     public String getHtml(){
302         return toString();
303     }
304     
305 
306 
307     /**
308      * 获取设置总数
309      * @return
310      */
311     public long getCount() {
312         return count;
313     }
314 
315     /**
316      * 设置数据总数
317      * @param count
318      */
319     public void setCount(long count) {
320         this.count = count;
321         if (pageSize >= count){
322             pageNo = 1;
323         }
324     }
325     
326     /**
327      * 获取当前页码
328      * @return
329      */
330     public int getPageNo() {
331         return pageNo;
332     }
333     
334     /**
335      * 设置当前页码
336      * @param pageNo
337      */
338     public void setPageNo(int pageNo) {
339         this.pageNo = pageNo;
340     }
341     
342     /**
343      * 获取页面大小
344      * @return
345      */
346     public int getPageSize() {
347         return pageSize;
348     }
349 
350     /**
351      * 设置页面大小(最大500)
352      * @param pageSize
353      */
354     public void setPageSize(int pageSize) {
355         this.pageSize = pageSize <= 0 ? 10 : pageSize;// > 500 ? 500 : pageSize;
356     }
357 
358     /**
359      * 首页索引
360      * @return
361      */
362     @JsonIgnore
363     public int getFirst() {
364         return first;
365     }
366 
367     /**
368      * 尾页索引
369      * @return
370      */
371     @JsonIgnore
372     public int getLast() {
373         return last;
374     }
375     
376     /**
377      * 获取页面总数
378      * @return getLast();
379      */
380     @JsonIgnore
381     public int getTotalPage() {
382         return getLast();
383     }
384 
385     /**
386      * 是否为第一页
387      * @return
388      */
389     @JsonIgnore
390     public boolean isFirstPage() {
391         return firstPage;
392     }
393 
394     /**
395      * 是否为最后一页
396      * @return
397      */
398     @JsonIgnore
399     public boolean isLastPage() {
400         return lastPage;
401     }
402     
403     /**
404      * 上一页索引值
405      * @return
406      */
407     @JsonIgnore
408     public int getPrev() {
409         if (isFirstPage()) {
410             return pageNo;
411         } else {
412             return pageNo - 1;
413         }
414     }
415 
416     /**
417      * 下一页索引值
418      * @return
419      */
420     @JsonIgnore
421     public int getNext() {
422         if (isLastPage()) {
423             return pageNo;
424         } else {
425             return pageNo + 1;
426         }
427     }
428     
429     /**
430      * 获取本页数据对象列表
431      * @return List<T>
432      */
433     public List<T> getList() {
434         return list;
435     }
436 
437     /**
438      * 设置本页数据对象列表
439      * @param list
440      */
441     public Page<T> setList(List<T> list) {
442         this.list = list;
443         initialize();
444         return this;
445     }
446 
447     /**
448      * 获取查询排序字符串
449      * @return
450      */
451     @JsonIgnore
452     public String getOrderBy() {
453         // SQL过滤,防止注入 
454         String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"
455                     + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
456         Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
457         if (sqlPattern.matcher(orderBy).find()) {
458             return "";
459         }
460         return orderBy;
461     }
462 
463     /**
464      * 设置查询排序,标准查询有效, 实例: updatedate desc, name asc
465      */
466     public void setOrderBy(String orderBy) {
467         this.orderBy = orderBy;
468     }
469 
470     /**
471      * 获取点击页码调用的js函数名称
472      * function ${page.funcName}(pageNo){location="${ctx}/list-${category.id}${urlSuffix}?pageNo="+i;}
473      * @return
474      */
475     @JsonIgnore
476     public String getFuncName() {
477         return funcName;
478     }
479 
480     /**
481      * 设置点击页码调用的js函数名称,默认为page,在一页有多个分页对象时使用。
482      * @param funcName 默认为page
483      */
484     public void setFuncName(String funcName) {
485         this.funcName = funcName;
486     }
487 
488     /**
489      * 获取分页函数的附加参数
490      * @return
491      */
492     @JsonIgnore
493     public String getFuncParam() {
494         return funcParam;
495     }
496 
497     /**
498      * 设置分页函数的附加参数
499      * @return
500      */
501     public void setFuncParam(String funcParam) {
502         this.funcParam = funcParam;
503     }
504 
505     /**
506      * 设置提示消息,显示在“共n条”之后
507      * @param message
508      */
509     public void setMessage(String message) {
510         this.message = message;
511     }
512     
513     /**
514      * 分页是否有效
515      * @return this.pageSize==-1
516      */
517     @JsonIgnore
518     public boolean isDisabled() {
519         return this.pageSize==-1;
520     }
521     
522     /**
523      * 是否进行总数统计
524      * @return this.count==-1
525      */
526     @JsonIgnore
527     public boolean isNotCount() {
528         return this.count==-1;
529     }
530     
531     /**
532      * 获取 Hibernate FirstResult
533      */
534     public int getFirstResult(){
535         int firstResult = (getPageNo() - 1) * getPageSize();
536         if (firstResult >= getCount() || firstResult<0) {
537             firstResult = 0;
538         }
539         return firstResult;
540     }
541     
542     /**
543      * 获取 Hibernate MaxResults
544      */
545     public int getMaxResults(){
546         return getPageSize();
547     }
548 
549 
550     
551 }

 

2. 分页类(Page<T>)中的工具类【 import com.common.utils.CookieUtils】

  1 import java.io.UnsupportedEncodingException;
  2 import java.net.URLDecoder;
  3 import java.net.URLEncoder;
  4 
  5 import javax.servlet.http.Cookie;
  6 import javax.servlet.http.HttpServletRequest;
  7 import javax.servlet.http.HttpServletResponse;
  8 
  9 /**
 10  * Cookie工具类
 11  * @author libingbin
 12  * @version 1.0
 13  */
 14 public class CookieUtils {
 15 
 16     /**
 17      * 设置 Cookie(生成时间为1天)
 18      * @param name 名称
 19      * @param value 值
 20      */
 21     public static void setCookie(HttpServletResponse response, String name, String value) {
 22         setCookie(response, name, value, 60*60*24);
 23     }
 24     
 25     /**
 26      * 设置 Cookie
 27      * @param name 名称
 28      * @param value 值
 29      * @param maxAge 生存时间(单位秒)
 30      * @param uri 路径
 31      */
 32     public static void setCookie(HttpServletResponse response, String name, String value, String path) {
 33         setCookie(response, name, value, path, 60*60*24);
 34     }
 35     
 36     /**
 37      * 设置 Cookie
 38      * @param name 名称
 39      * @param value 值
 40      * @param maxAge 生存时间(单位秒)
 41      * @param uri 路径
 42      */
 43     public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) {
 44         setCookie(response, name, value, "/", maxAge);
 45     }
 46     
 47     /**
 48      * 设置 Cookie
 49      * @param name 名称
 50      * @param value 值
 51      * @param maxAge 生存时间(单位秒)
 52      * @param uri 路径
 53      */
 54     public static void setCookie(HttpServletResponse response, String name, String value, String path, int maxAge) {
 55         Cookie cookie = new Cookie(name, null);
 56         cookie.setPath(path);
 57         cookie.setMaxAge(maxAge);
 58         try {
 59             cookie.setValue(URLEncoder.encode(value, "utf-8"));
 60         } catch (UnsupportedEncodingException e) {
 61             e.printStackTrace();
 62         }
 63         response.addCookie(cookie);
 64     }
 65     
 66     /**
 67      * 获得指定Cookie的值
 68      * @param name 名称
 69      * @return 70      */
 71     public static String getCookie(HttpServletRequest request, String name) {
 72         return getCookie(request, null, name, false);
 73     }
 74     /**
 75      * 获得指定Cookie的值,并删除。
 76      * @param name 名称
 77      * @return 78      */
 79     public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name) {
 80         return getCookie(request, response, name, true);
 81     }
 82     /**
 83      * 获得指定Cookie的值
 84      * @param request 请求对象
 85      * @param response 响应对象
 86      * @param name 名字
 87      * @param isRemove 是否移除
 88      * @return 89      */
 90     public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name, boolean isRemove) {
 91         String value = null;
 92         Cookie[] cookies = request.getCookies();
 93         if (cookies != null) {
 94             for (Cookie cookie : cookies) {
 95                 if (cookie.getName().equals(name)) {
 96                     try {
 97                         value = URLDecoder.decode(cookie.getValue(), "utf-8");
 98                     } catch (UnsupportedEncodingException e) {
 99                         e.printStackTrace();
100                     }
101                     if (isRemove) {
102                         cookie.setMaxAge(0);
103                         response.addCookie(cookie);
104                     }
105                 }
106             }
107         }
108         return value;
109     }
110 }

 

3. Service基类中(查询分页数据的方法)

 1 /**
 2  * 查询分页数据
 3  * @param page 分页对象
 4  * @param entity
 5  * @return
 6  */
 7 public Page<T> findPage(Page<T> page, T entity) {  
 8 
 9 
10 
11     entity.setPage(page);    //每个实体中需有当前实体分页对象封装为基类会比较方便protected Page<T> page;        //当前实体分页对象
12     
13     page.setList(dao.findList(entity));   //根据实体查询所有,返回结果为List集合   
14     
15     return page;
16 }

 

备注:

Controller层示例:
1 @RequestMapping(value = "list")
2 public String list(Demo demo, HttpServletRequest request, HttpServletResponse response, Model model) {
3     Page<Demo> page = DemoService.findPage(new Page<Demo>(request, response), demo); 
4     model.addAttribute("page", page);
5     return "demo/demoList";
6 }

 

 

4.  page.tag 标签【位置:/WEB-INF/tags/table/page.tag】

 1 <%@ tag language="java" pageEncoding="UTF-8"%>
 2 
 3 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 4 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
 5 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
 6 <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
 7 
 8 <%@ taglib prefix="table" tagdir="/WEB-INF/tags/table" %> 
 9 
10 <c:set var="ctx" value="${pageContext.request.contextPath}${fns:getAdminPath()}"/>
11 <c:set var="ctxStatic" value="${pageContext.request.contextPath}/static"/>
12 
13 <%@ attribute name="page" type="com.common.persistence.Page" required="true"%>
14 <%-- 表格分页工具栏,使用方法: 原样输出page --%>
15 ${page}
16 <!-- pagination的css样式设定-->
17 <style>
18 .fixed-table-pagination div.pagination,
19 .fixed-table-pagination div.pagination-roll,
20 .fixed-table-pagination .pagination-detail {
21     margin-top: 0px;
22     margin-bottom: 10px;
23 }
24 
25 .fixed-table-pagination div.pagination-roll .pagination,
26 .fixed-table-pagination div.pagination .pagination {
27     margin: 0;
28 }
29 
30 .fixed-table-pagination .pagination a {
31     padding: 6px 12px;
32     line-height: 1.428571429;
33 }
34 
35 .fixed-table-pagination .pagination-info {
36     line-height: 34px;
37     margin-right: 5px;
38 }
39 
40 .fixed-table-pagination .btn-group {
41     position: relative;
42     display: inline-block;
43     vertical-align: middle;
44 }
45 
46 .fixed-table-pagination .dropup .dropdown-menu {
47     margin-bottom: 0;
48 }
49 
50 .fixed-table-pagination .page-list {
51     display: inline-block;
52 }
53 
54 </style>

 

5. 在jsp页面中只需要添加上述标签即可

1             <!-- 分页代码 -->
2 <table:page page="${page}"></table:page>        

 

<!-- Start -->

获知及时信息,请关注我的个人微信订阅号:0与1的那点事

<!-- End -->

 

本文为博主原创文章,转载请注明出处!

http://www.cnblogs.com/libingbin/

感谢您的阅读。

posted on 2016-09-27 22:49  bingbinlee  阅读(384)  评论(0编辑  收藏  举报