分页实现
对于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/
感谢您的阅读。