[背景] 最近学习Spring MVC,涉及到分页显示的问题,准备自己整理一个分页工具。由于以前使用Strus框架使用 NewPandaKing 的一个PageBean和Page方法,耦合性比较高,于是优化一下。
[优点] 耦合低,使用方便。
[缺点] 由于耦合低,不查数据库,所以每次使用List的sublist方法,效率降低。
代码如下:
分页工具类:PageUtil.java
1 /**
2 * Java 分页工具类
3 */
4 package com.common.tool.util;
5
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9
10 /**
11 * @author neuhxy
12 * @version 2015-4-23 15:25:21
13 *
14 */
15 public class PageUtil {
16
17 private int page = 1; // 当前页
18 public int total = 0; // 总页数
19 private int size = 10; // 每页5条数据
20 private int slice = 5; // 切片,当页大于切片时,进行分页处理
21 private int totalRows = 0; // 总数据数
22 private int pageStartRow = 0;// 每页的起始数
23 private int pageEndRow = 0; // 每页显示数据的终止数
24 private boolean hasNextPage = false; // 是否有下一页
25 private boolean hasPreviousPage = false; // 是否有前一页
26 private List<?> list; // 分页组件包含的集合
27 private List<?> show; // 分页中需要显示的List
28 private String action; // 设置跳转URL
29 private String method = "GET"; // 使用POST或者GET请求
30 @SuppressWarnings("unused")
31 private String code1; // 分页组件的现实代码
32 @SuppressWarnings("unused")
33 private String code2; // 分页组件的现实代码
34 private Map<String, Object> map = new HashMap<String, Object>(); // 隐含条件
35 public int[] sizeArray = { 10, 20, 50, 100, 1000, 5000 }; // 设置几种可以显示的条数
36
37 // 默认构造函数
38 public PageUtil() {
39 }
40
41 /**
42 * 分页初始化
43 *
44 * @param list
45 * @param size
46 */
47 public void init(List<?> initList, int pageSize) {
48 if (null != initList) {
49
50 this.setSize(pageSize);
51 this.setList(initList);
52
53 totalRows = initList.size();
54
55 hasPreviousPage = false;
56
57 if ((totalRows % this.getSize()) == 0) {
58 total = totalRows / this.getSize();
59 } else {
60 total = totalRows / this.getSize() + 1;
61 }
62
63 if (page >= total) { hasNextPage = false; } else { hasNextPage = true; }
64
65 if (totalRows < this.getSize()) {
66 this.pageStartRow = 0;
67 this.pageEndRow = totalRows;
68 } else {
69 this.pageStartRow = 0;
70 this.pageEndRow = this.getSize();
71 }
72 this.setShow(getShow(this.getPage()));
73 }
74
75 }
76
77 // 第一种样式 <ul> / <li> 格式
78 public String getCode1() {
79
80 StringBuffer sb = new StringBuffer();
81 sb.append("<form style='text-align:center;' action=\"" + getAction() + "\" method=\"" + getMethod() + "\">");
82 sb.append("<ul class=\"pagination\">");
83
84 // 判断是否有上一页
85 if (isHasPreviousPage()) {
86 sb.append("<li><a href=\"" + getAction() + "?page=1\">«</a></li>");
87 sb.append("<li><a href=\"" + getAction() + "?page=" + (getPage() - 1) + "\"><</a></li>");
88 } else {
89 sb.append("<li class=\"disabled\"><a href=\"#\">«</a></li>");
90 sb.append("<li class=\"disabled\"><a href=\"#\"><</a></li>");
91 }
92
93 // 中间显示
94 // 当总页数大于切片时,才显示 ... 分页效果
95 if (getTotal() > getSlice()) {
96
97 // 如果当前页码在 1 - getSlice(),显示右侧 ... 翻页按钮
98 if (getPage() > 0 && getPage() <= getSlice()
99 && getPage() < getTotal() - getSlice()) {
100 for (int i = 1; i <= getSlice(); i++) {
101 String spanClzz = "<li><a href=\"" + getAction() + "?page=" + i + "\"> " + i + " <span class=\"sr-only\">(current)</span></a></li>";
102
103 if (this.page == i) {
104 spanClzz = "<li class=\"active\"><a href=\"#\">" + i + " <span class=\"sr-only\">(current)</span></a></li>";
105 }
106 sb.append(spanClzz);
107 // 当总页数大于3 的时候 添加右侧 ... 分页
108 }
109 if (getTotal() > getSlice() +1 ) {
110 String dotClzz = "<li><a href=\"" + getAction() + "?page=" + (getSlice() +1) + "\"> ... <span class=\"sr-only\">(current)</span></a></li>";
111 sb.append(dotClzz);
112 }
113
114 }
115 // 如果当前页码在6 到 total - 6 页,显示两端的两个 ...翻页按钮
116 if (getPage() > getSlice() && getPage() <= getTotal() - getSlice()) {
117 String dotClzz = "<li><a href=\""
118 + getAction()
119 + "?page="
120 + (getPage() - ((getSlice() + 1) / 2))
121 + "\"> ... <span class=\"sr-only\">(current)</span></a></li>";
122 sb.append(dotClzz);
123 for (int i = getPage() - ((getSlice() - 1) / 2); i <= getPage()
124 + ((getSlice() - 1) / 2); i++) {
125 String spanClzz = "<li><a href=\""
126 + getAction()
127 + "?page="
128 + i
129 + "\"> "
130 + i
131 + " <span class=\"sr-only\">(current)</span></a></li>";
132
133 if (this.page == i) {
134 spanClzz = "<li class=\"active\"><a href=\"#\">"
135 + i
136 + " <span class=\"sr-only\">(current)</span></a></li>";
137 }
138 sb.append(spanClzz);
139 // 当总页数大于getSlice() 的时候 添加右侧 ... 分页
140
141 }
142 dotClzz = "<li><a href=\""
143 + getAction()
144 + "?page="
145 + (getPage() + ((getSlice() + 1) / 2))
146 + "\"> ... <span class=\"sr-only\">(current)</span></a></li>";
147 sb.append(dotClzz);
148
149 }
150 // 如果当前页码在total-getSlice() 到 total 页,左侧显示一个...翻页按钮
151 if (getPage() > 0 && getPage() > getTotal() - getSlice()
152 && getPage() <= getTotal()) {
153
154 String dotClzz = "<li><a href=\""
155 + getAction()
156 + "?page="
157 + (getTotal() - getSlice())
158 + "\"> ... <span class=\"sr-only\">(current)</span></a></li>";
159 sb.append(dotClzz);
160 int s = getTotal() - getSlice() + 1 > 0 ? getTotal()
161 - getSlice() + 1 : 1;
162 for (int i = s; i <= getTotal(); i++) {
163 String spanClzz = "<li><a href=\""
164 + getAction()
165 + "?page="
166 + i
167 + "\"> "
168 + i
169 + " <span class=\"sr-only\">(current)</span></a></li>";
170
171 if (this.page == i) {
172 spanClzz = "<li class=\"active\"><a href=\"#\">"
173 + i
174 + " <span class=\"sr-only\">(current)</span></a></li>";
175 }
176 sb.append(spanClzz);
177 }
178
179 }
180 } else {
181 // 否则直接显示,有几页显示几页,不加...
182 for (int i = 1; i <= getTotal(); i++) {
183 String spanClzz = "<li><a href=\"" + getAction() + "?page=" + i
184 + "\"> " + i
185 + " <span class=\"sr-only\">(current)</span></a></li>";
186
187 if (this.page == i) {
188 spanClzz = "<li class=\"active\"><a href=\"#\">"
189 + i
190 + " <span class=\"sr-only\">(current)</span></a></li>";
191 }
192 sb.append(spanClzz);
193 // 当总页数大于getSlice() 的时候 添加右侧 ... 分页
194
195 }
196 }
197
198 // 判断是否有下一页
199 if (isHasNextPage()) {
200 sb.append("<li><a href=\"" + getAction() + "?page="
201 + (getPage() + 1) + "\">></a></li>");
202 sb.append("<li><a href=\"" + getAction() + "?page=" + getTotal()
203 + "\">»</a></li>");
204 } else {
205 sb.append("<li class=\"disabled\"><a href=\"#\">></a></li>");
206 sb.append("<li class=\"disabled\"><a href=\"#\">»</a></li>");
207 }
208
209 sb.append("</ul></form>");
210 return sb.toString();
211 }
212
213 // 第二种分页样式 <a> 带分页现实多少条记录设置
214 public String getCode2() {
215
216 StringBuffer sb = new StringBuffer();
217 String code = "<div class=\"pager clearfix text-center\">";
218 String scripts = "<script> " + "function subPage(p){"
219 + "document.pageForm.elements['page'].value = p;"
220 + "document.pageForm.submit();" + "} "
221 + " function subPageSize(pageSize){ "
222 + " document.pageForm.submit();" + "}</script>";
223
224 setMethod("POST");
225 code += "<form name=\"pageForm\" action=\"" + getAction()
226 + "\" method=\"" + getMethod() + "\">";
227
228 String hidden = "<input type=\"hidden\" name=\"page\" value=\"" + page
229 + "\">";
230 if (!map.isEmpty()) {
231 for (String key : map.keySet()) {
232 System.out.println("key= " + key + " and value= "
233 + map.get(key));
234 hidden += "<input type=\"hidden\" name=\"" + key
235 + "\" value=\"" + map.get(key) + "\" />";
236 }
237 }
238 code += hidden;
239 code += scripts;
240
241 // 底面样式 首页 上一页
242 if (getPage() != 1) {
243 code += "<a href=\"javascript:subPage(1)\">首页</a> "
244 + "<a href=\"javascript:subPage(" + (this.getPage() - 1)
245 + ")\">上一页</a> ";
246 } else {
247 code += "<span>首页</span> " + "<span>上一页</span> ";
248 }
249
250 // 跳第几页
251 code += "第<select style=\"width:60px;\" οnchange=\"javascript:subPage(this.value)\" class=\"numbox\">";
252 for (int i = 1; i <= getTotal(); i++) {
253 if (i == this.getPage()) {
254 code += "<option value=" + i + " selected='selected'>" + i
255 + "</option>";
256 } else {
257 code += "<option value=" + i + ">" + i + "</option>";
258 }
259 }
260 code += "</select>页,共" + this.getTotal() + "页";
261
262 // 每页显示几个记录
263 code += ",每页显示<select style=\"width:60px;\" name=\"size\" οnchange=\"javascript:subPageSize(this.value)\" class=\"numbox\">";
264 for (int j = 0; j < sizeArray.length; j++) {
265 if (sizeArray[j] == getSize()) {
266 code += "<option value=" + sizeArray[j]
267 + " selected='selected'>" + sizeArray[j] + "</option>";
268 } else {
269 code += "<option value=" + sizeArray[j] + ">" + sizeArray[j]
270 + "</option>";
271 }
272 }
273
274 code += "</select>条记录";
275
276 // 下一页 尾页
277 if (getPage() != getTotal()) {
278 code += "<a href=\"javascript:subPage(" + (getPage() + 1)
279 + ")\">下一页</a> " + "<a href=\"javascript:subPage("
280 + getTotal() + ")\">尾页</a>";
281 } else {
282 code += "<span>下一页</span> " + "<span>尾页</span> ";
283 }
284 code += "</div>";
285 sb.append(code);
286 sb.append("</form>");
287 return sb.toString();
288 }
289
290 // 判断要不要分页
291 public boolean isNext() {
292 return list.size() > getSlice();
293 }
294
295 public void setHasPreviousPage(boolean hasPreviousPage) {
296 this.hasPreviousPage = hasPreviousPage;
297 }
298
299 // 获取下一个内容
300 public List<?> getNextPage() {
301 page = page + 1;
302 disposePage();
303 return getShow(page);
304 }
305
306 // 处理分页
307 private void disposePage() {
308 if (page == 0) {
309 page = 1;
310 }
311 if ((page - 1) > 0) {
312 hasPreviousPage = true;
313 } else {
314 hasPreviousPage = false;
315 }
316
317 if (page >= total) {
318 hasNextPage = false;
319 } else {
320 hasNextPage = true;
321 }
322 }
323
324 // 获取上一页内容
325 public List<?> getPreviousPage() {
326 page = page - 1;
327
328 if ((page - 1) > 0) {
329 hasPreviousPage = true;
330 } else {
331 hasPreviousPage = false;
332 }
333 if (page >= total) {
334 hasNextPage = false;
335 } else {
336 hasNextPage = true;
337 }
338 return getShow(page);
339 }
340
341 public List<?> getShow() {
342 return show;
343 }
344
345 // 获取第 n 页内容
346 public List<?> getShow(int page) {
347
348 if (page == 0) {
349 this.setPage(1);
350 page = 1;
351 } else {
352 this.setPage(page);
353 }
354
355 this.disposePage();
356
357 if (page * size < totalRows) {// 判断是否为最后一页
358 pageEndRow = page * size;
359 pageStartRow = pageEndRow - size;
360 } else {
361 pageEndRow = totalRows;
362 pageStartRow = size * (total - 1);
363 }
364
365 List<?> show = null;
366 if (!list.isEmpty()) {
367 show = list.subList(pageStartRow, pageEndRow);
368 }
369 return show;
370 }
371
372 // 获取第一页内容
373 public List<?> getFistPage() {
374 if (this.isNext()) {
375 return list.subList(0, size);
376 } else {
377 return list;
378 }
379 }
380
381 public int getPage() {
382 return page;
383 }
384
385 public void setPage(int page) {
386 this.page = page;
387 }
388
389 public int getTotal() {
390 return total;
391 }
392
393 public void setTotal(int total) {
394 this.total = total;
395 }
396
397 public int getSize() {
398 return size;
399 }
400
401 public void setSize(int size) {
402 this.size = size;
403 }
404
405 public int getTotalRows() {
406 return totalRows;
407 }
408
409 public void setTotalRows(int totalRows) {
410 this.totalRows = totalRows;
411 }
412
413 public int getPageStartRow() {
414 return pageStartRow;
415 }
416
417 public void setPageStartRow(int pageStartRow) {
418 this.pageStartRow = pageStartRow;
419 }
420
421 public int getPageEndRow() {
422 return pageEndRow;
423 }
424
425 public void setPageEndRow(int pageEndRow) {
426 this.pageEndRow = pageEndRow;
427 }
428
429 public boolean isHasNextPage() {
430 return hasNextPage;
431 }
432
433 public void setHasNextPage(boolean hasNextPage) {
434 this.hasNextPage = hasNextPage;
435 }
436
437 public List<?> getList() {
438 return list;
439 }
440
441 public void setList(List<?> list) {
442 this.list = list;
443 }
444
445 public boolean isHasPreviousPage() {
446 return hasPreviousPage;
447 }
448
449 public String getAction() {
450 return action;
451 }
452
453 public void setAction(String action) {
454 this.action = action;
455 }
456
457 public String getMethod() {
458 return method;
459 }
460
461 public void setMethod(String method) {
462 this.method = method;
463 }
464
465 public Map<String, Object> getMap() {
466 return map;
467 }
468
469 public void setMap(Map<String, Object> map) {
470 this.map = map;
471 }
472
473 public void setShow(List<?> show) {
474 this.show = show;
475 }
476
477 public void setCode1(String code1) {
478 this.code1 = code1;
479 }
480
481 public void setCode2(String code2) {
482 this.code2 = code2;
483 }
484
485 public int getSlice() {
486 return slice;
487 }
488
489 public void setSlice(int slice) {
490 this.slice = slice;
491 }
492
493 public int[] getSizeArray() {
494 return sizeArray;
495 }
496
497 public void setSizeArray(int[] sizeArray) {
498 this.sizeArray = sizeArray;
499 }
500
501 }
Spring-MVC Controller部分: UserController.java
@RequestMapping("view_user")
public String view_user(PageUtil p, HttpServletRequest request) {
//……仅提供部分关键代码
//分页组件用法:首先获取所有List
List<User> list = userService.getUserList();
pu.init(list, pu.getSize());
pu.setShow(pu.getShow(p.getPage()));
//告诉分页跳转URL, 对应这个方法本身的路径
pu.setAction("../user/view_user");
request.setAttribute("pu", pu);
return "admin/view_user";
}
在页面上显示部分:view_user.jsp
<c:if test="${!empty pu.show}">
<c:forEach items="${pu.show}" var="item">
<td>${item.id }</td>
<!--显示具体内容-->
</c:forEach>
</c:if>
<!-- 以下两种方式任选其一 -->
<!--显示分页代码1 使用Bootstrap 库样式 需要额外引入bootstrap.css -->
${pu.code1}
<!--显示分页代码1, 使用默认样式, 功能全 -->
${pu.code2}
[1]
效果预览: