站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Java 专题分页,心中的痛?

分页,心中的痛?

摘要: 分页,心中的痛?

</td> </tr> <tr> <td height="35" valign="top" class="ArticleTeitle"> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="270" height="86" align="center" valign="top"> </td> <td width="414" valign="top">


分页,这是Web应用中经常要涉及的问题,相信每一位开发人员都有这个自信解决这个问题,看了不少各式各样的分页实现代码,总觉得应该有一个比较好的规范来处理分页。有没有一个比较好、规范的分页接口,这样大家都可以围绕此接口做实现,这样分页处理就统一起来,简单多,而不我们看到现象:不同公司个人的不同版本的分页实现。

个人非常欣赏aopalliance项目,虽然只是一些接口的定义,但定于规范化AOP确实做出不小的贡献,不然不同的AOP实现的互通如何实现?规范的作用就发挥出来啦。

在Hibernate的站点上有一个分页的参考实现:
: http://www.hibernate.org/248.html
定义了分页处理所需的接口Page,这个接口非常不错,至少是我目前看到最完善和合理的(关于分页处理),将分页的信息全部包含啦,简单明了,代码如下:</td> </tr> <tr> <td height="20" colspan="2">

  1. public interface Page {
  2. boolean isFirstPage();
  3. boolean isLastPage();
  4. boolean hasNextPage();
  5. boolean hasPreviousPage();
  6. int getLastPageNumber();
  7. List getThisPageElements();
  8. Logger getLogger();
  9. int getTotalNumberOfElements();
  10. int getThisPageFirstElementNumber();
  11. int getThisPageLastElementNumber();
  12. int getNextPageNumber();
  13. int getPreviousPageNumber();
  14. int getPageSize();
  15. int getPageNumber();
  16. }

这里可能要做一些调整,个人觉得getLogger()没有必要放在这个接口中,它是用于处理日志的,这个可以在具体的实现代码完成,getThisPageElements()获取当前页的数据,这里返回为List类型数据,这里可能需要更改一下返回类型,当前页的数据可能涉及许多种类型:数组、RowSet、List等等,所以我们拟定将其返回值定为Object,在具体的代码中再去考虑究竟返回何种类型,所以这个接口修改后如下:

  1. public interface Page {
  2. boolean isFirstPage();
  3. boolean isLastPage();
  4. boolean hasNextPage();
  5. boolean hasPreviousPage();
  6. int getLastPageNumber();
  7. Object getThisPageElements();
  8. int getTotalNumberOfElements();
  9. int getThisPageFirstElementNumber();
  10. int getThisPageLastElementNumber();
  11. int getNextPageNumber();
  12. int getPreviousPageNumber();
  13. int getPageSize();
  14. int getThisPageNumber ();
  15. }

接口定义完毕后我们需要根据实际情况实现这个接口,这里主要讲三种情况:Hibernate的Query分页、Jdbc的ResultSet分页和List数据类型分页。在Hibernate的站点上提供了一个Hibernate分页的实现类HibernatePage,这个类处理从0开始,这可能与我们的实际情况不太一样,同时可能还有一些分页处理方面的bug,让我们看看HibernatePage的一个具体实现:

  1. /**
  2. * Hibernate分页信息
  3. */
  4. public class HibernatePage implements Page
  5. {
  6. private List elements;
  7. private int pageSize;
  8. private int pageNumber;
  9. private int totalElements = 0;
  10. /**
  11. * 构建HibernatePage对象,完成Hibernate的Query数据的分页处理
  12. *
  13. * @param query Hibernate的Query对象
  14. * @param pageNumber 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。
  15. * 如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。
  16. * 这两种情况将重新更改当前页的页码,为最后一页编码。
  17. * @param pageSize 每一页显示的条目数
  18. */
  19. public HibernatePage(Query query, int pageNumber, int pageSize)
  20. {
  21. this.pageNumber = pageNumber;
  22. this.pageSize = pageSize;
  23. try
  24. {
  25. ScrollableResults scrollableResults = query.scroll();
  26. //get the total elements number
  27. scrollableResults.last();
  28. this.totalElements = scrollableResults.getRowNumber();
  29. if (Integer.MAX_VALUE == this.pageNumber || this.pageNumber > getLastPageNumber()) //last page
  30. {
  31. this.pageNumber = getLastPageNumber();
  32. }
  33. elements = query.setFirstResult((this.pageNumber - 1) * this.pageSize).setMaxResults(this.pageSize + 1).list();
  34. } catch (HibernateException e)
  35. {
  36. throw new RuntimeException(e);
  37. }
  38. }
  39. public boolean isFirstPage()
  40. {
  41. return getThisPageNumber() == 1;
  42. }
  43. public boolean isLastPage()
  44. {
  45. return getThisPageNumber() >= getLastPageNumber();
  46. }
  47. public boolean hasNextPage()
  48. {
  49. return getLastPageNumber() > getThisPageNumber();
  50. }
  51. public boolean hasPreviousPage()
  52. {
  53. return getThisPageNumber() > 1;
  54. }
  55. public int getLastPageNumber()
  56. {
  57. return totalElements % this.pageSize == 0 ? totalElements / this.pageSize : totalElements / this.pageSize + 1;
  58. }
  59. /**
  60. * 返回List类型数据
  61. *
  62. * @return List数据源
  63. */
  64. public Object getThisPageElements()
  65. {
  66. return elements;
  67. }
  68. public int getTotalNumberOfElements()
  69. {
  70. return totalElements;
  71. }
  72. public int getThisPageFirstElementNumber()
  73. {
  74. return (getThisPageNumber() - 1) * getPageSize() + 1;
  75. }
  76. public int getThisPageLastElementNumber()
  77. {
  78. int fullPage = getThisPageFirstElementNumber() + getPageSize() - 1;
  79. return getTotalNumberOfElements() < fullPage ? getTotalNumberOfElements() : fullPage;
  80. }
  81. public int getNextPageNumber()
  82. {
  83. return getThisPageNumber() + 1;
  84. }
  85. public int getPreviousPageNumber()
  86. {
  87. return getThisPageNumber() - 1;
  88. }
  89. public int getPageSize()
  90. {
  91. return pageSize;
  92. }
  93. public int getThisPageNumber()
  94. {
  95. return pageNumber;
  96. }
  97. }

当然上述只是参考实现,你可以依据自己的分页算法进行实现,只要遵循这个接口即可。这里就不在给出List和ResultSet分页的实现逻辑,附件包含了源代码,大家可以参考一下。

总结:分页处理并不难,关键是没有一个好的接口和指导如何去实现的思想,这样造成了许多不规范,Hibernate站点上的Page接口设计的非常不错,同时给出了如何去实现的指导,相信有了一个规范接口和相关的实现逻辑,这样就分页处理就规范化多啦。

</td> </tr> </table> </td> </tr> <tr>


↑返回目录
前一篇: java实现的表达式编译器
后一篇: 震动的窗口