Page.java 17 KB

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