`

通用分页实现及其OO设计探讨——转载

    博客分类:
  • JAVA
阅读更多

分页是一种常用的页面数据显示技术,分页能够通过减少页面数据处理量从而提高了系统的性能。分页应该是做WEB开发必须掌握的一个小技术。而分页却是复杂的,倒不是它的技术有多复杂;而是有太多的重复代码,这些代码都难以重用。能不能实现一个通用的分页框架?每次只需要去覆写一两个方法,通过少量的代码就能实现分页的功能?

一、一般分页应该要具有的功能有:
    1.  
灵活的设置分页大小。可以动态的设置分页大小,而不是写死到代码中。
    2.  
自动计算总页数。根据分页大小和总记录数自动计算总页数。
    3.  
获得当前页的页号。
    4.  
获得当前页的总记录数。一般是最后一页的时候可能会小于分页大小。
    5.  
判断当前页是否为第一页。
    6.  
判断当前页是否为最后一页。
    7.  
判断当前页是否有上一页。
    8.  
判断当前页是否有下一页。
    9.  
获得当前页的数据列表。
    10.
获得当前页的第一条记录的索引号
    11.
获得当前页的最后一条记录的索引号。 
       

二、常用的分页技术
   
目前常用的分页技术有两种:
    1.
第一次访问是读取所有记录,放入session中,然后每次从session对象中读取当前页的数据
    2.
每次都访问数据库,从数据库中读取当前页的记录。
   
这两种方法都各有优缺点,当数据量比较少时,第一种方法无疑是要快一些,因为减少与数据库的连接访问。而当数据量比较大时,比如查询结果可能会是上万条,那么内存的开销是十分大的,放到session中还有一个问题是能不能及时的清除无用的对象。而且这么大数据量在网络中传输也会使系统变得很慢。
第二种方法就是专门解决这个问题的,它每次访问数据库,只读取当前页所需的记录,大大的减少网络传输量;它不会把页数据放到session中,大大提高服务器的性能。
所以第二种方式要优于第一种方法。Session不要乱用,要用也仅仅是存放一些公共变量,相对于占用空间比较少的对象。不适合存放大量的数据,否则在很多个用户同时访问时那么系统会很慢,因为服务器内存被销耗的很厉害。

三、通用分页框架需要解决的问题
作为一个通用分页框架,
1应该不依赖于任何其它框架
2应该支持多种数据库
3应该可以应用于任何web框架中,如:struts,spring等。
4应该把数据访问的具体实现留给用户去实现。
5应该实现关键的算法和过程,如:计算总页数,所需的实始化动作。
6应该减化Contrller控制器的代码,以往的分页技术在Contrller中存在太多的       if…else代码。十分难懂,应该由一个辅助类来实现。
7应该减化jsp页面的代码,页面应该没有任何与分页相关的计算。应该由分页对象来实现。
8应该支持两种分页方式,采用session或不采用session由用户控制。
 
四、具体实现
        1.通用分页接口。定义接口可以有更多不同的实现,接口只声明了分页应该具有的公共行为。
                 
java 代码
  1. ViewPage.java   
  2. /**  
  3. * 分页接口  
  4. */  
  5. public interface ViewPage {   
  6.   
  7.   
  8.   
  9. /**  
  10. * 获取总页数  
  11. * @return 总页数  
  12. */  
  13. public int getPageCount();   
  14.   
  15.   
  16. /**  
  17. * 获得页面大小  
  18. * @return 页面大小  
  19. */  
  20. public int getPageSize();   
  21.   
  22.   
  23. /**  
  24. * 设置页面大小  
  25. * @param size  
  26. */  
  27. public void setPageSize(int size);   
  28. /**  
  29. * 获得当前页数据  
  30. * @return 数据列表  
  31. */  
  32. public List getPageData();   
  33.   
  34.   
  35. /**  
  36. * 获得当前页索引号  
  37. * @return 当前页索引号  
  38. */  
  39. public int getPageIndex();   
  40.   
  41. /**  
  42. * 获得当前页记录总数  
  43. * @return 当前页记录总数  
  44. */  
  45. public int getPageRows();   
  46.   
  47. /**  
  48. * 是否有下一页  
  49. * @return   
  50. */  
  51. public boolean getHashNextPage();   
  52.   
  53.   
  54. /**  
  55. * 是否有上一页  
  56. * @return  
  57. */  
  58. public boolean getHashPreviousPage();   
  59.   
  60. /**  
  61. * 转到尾页  
  62. *  
  63. */  
  64. public void gotoLastPage();   
  65. /**  
  66. * 转到首页  
  67. *  
  68. */  
  69. public void gotoFirstPage();   
  70.   
  71. /**  
  72. * 是否首页  
  73. * @return   
  74. */  
  75. public boolean isFirstPage();   
  76.   
  77. /**  
  78. * 是否尾页  
  79. * @return  
  80. */  
  81. public boolean isLastPage();   
  82.   
  83. /**  
  84. * 转到上一页  
  85. *  
  86. */  
  87. public void gotoPreviousPage();   
  88.   
  89. /**  
  90. * 转到下一页  
  91. *  
  92. */  
  93. public void gotoNextPage();   
  94.   
  95. /**  
  96. * 转到指定页面,pageIndex小于1时,转到第一页;pageIndex大于总页数时,转到最尾页  
  97. * @param pageIndex 指定的页号  
  98. */  
  99. public void gotoPage(int pageIndex);   
  100.   
  101. /**  
  102. * 获取当前页第一条记录的记录号  
  103. * @return int 当前页第一条记录的记录号  
  104. */  
  105. public int getPageFirstRecord();   
  106.   
  107. /**  
  108. * 获取当前页最后一条记录的记录号  
  109. * @return int 当前页最后一条记录的记录号  
  110. */  
  111. public int getPageLastRecord();   
  112.   
  113. }   

2分页抽像实现类,实现关键的算法
java 代码
  1. AbstractViewPage.java   
  2. /**  
  3. * 分页默认抽象实现  
  4. * 初始时,分页类有下列默认值:  
  5. * 分页大小为-1,为不分页;  
  6. * 总页数为1页  
  7. * 当前页为第一页  
  8. * 总记录数为0条  
  9. * 当前页数据列表为没有任何记录的列表  
  10. *  
  11. */  
  12. public abstract class AbstractViewPage implements ViewPage {   
  13.   
  14. //-----------------------------------------   
  15. //私有静态常量   
  16. //-----------------------------------------   
  17.   
  18. private static final int DEFAULT_PAGE_INDEX = 1;   
  19.   
  20. private static final int DEFALT_PAGE_COUNT = 1;   
  21.   
  22. private static final int DEFAULT_PAGE_SIZE = -1;   
  23.   
  24. private static final int DEFAULT_ROWS = 0;   
  25.   
  26. //-----------------------------------------   
  27. //私有成员变量   
  28. //-----------------------------------------   
  29.   
  30. /**当前页索引号**/  
  31. private int pageIndex = DEFAULT_PAGE_INDEX;   
  32. /**总页数**/  
  33. private int pageCount =DEFALT_PAGE_COUNT;   
  34.   
  35. /**分页大小**/  
  36. private int pageSize = DEFAULT_PAGE_SIZE ;   
  37.   
  38. /**数据总记录数**/  
  39. private int rows = DEFAULT_ROWS;   
  40.   
  41.   
  42. //------------------------------------------   
  43. //本地成员变量getter,setter方法   
  44. //------------------------------------------   
  45.   
  46.   
  47. /**  
  48. * 设置新页号,只有大于等于1而且小于等于总页数并且不为当前页时,才允许设置  
  49. * @param pageIndex The pageIndex to set.  
  50. */  
  51. private void setPageIndex(int newPageIndex) {   
  52.   
  53. if( newPageIndex >= this.DEFAULT_PAGE_INDEX && newPageIndex <= this.getPageCount() && newPageIndex != this.pageIndex) {   
  54. this.pageIndex = newPageIndex;   
  55. }   
  56.   
  57. }   
  58.   
  59. /**  
  60. * @return Returns the rows.  
  61. */  
  62. private int getRows() {   
  63. return rows;   
  64. }   
  65.   
  66. /**  
  67. * @param rows The rows to set.  
  68. */  
  69. private void setRows(int rows) {   
  70. this.rows = rows;   
  71. }   
  72. /**  
  73. * @param pageCount The pageCount to set.  
  74. */  
  75. private void setPageCount(int pageCount) {   
  76. this.pageCount = pageCount;   
  77. }   
  78.   
  79.   
  80.   
  81. //--------------------------------------   
  82. //实现Page接口方法   
  83. //--------------------------------------   
  84.   
  85.   
  86. /**  
  87. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageData()  
  88. */  
  89. public List getPageData() {   
  90. List pageList =null;   
  91.   
  92. //获得当前页数据   
  93. pageList = this.pageList(this.getPageFirstRecord(), this.getPageRows());   
  94. //保证不返回null   
  95. if(pageList == null) {   
  96. pageList =new ArrayList();   
  97. }   
  98. return pageList;   
  99.   
  100. }   
  101.   
  102. /**   
  103. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageIndex()  
  104. */  
  105. public int getPageIndex() {   
  106. return this.pageIndex;   
  107. }   
  108. /**  
  109. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#isFirstPage()  
  110. */  
  111. public boolean isFirstPage() {   
  112.   
  113. return this.DEFAULT_PAGE_INDEX ==this.pageIndex;   
  114. }   
  115. /**  
  116. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#isLastPage()  
  117. */  
  118. public boolean isLastPage() {   
  119. //当前页索引为总页数时为最后一页   
  120. return this.pageIndex == this.pageCount;   
  121. }    
  122.   
  123. /**  
  124. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getHashNextPage()  
  125. */  
  126. public boolean getHashNextPage() {   
  127. //当前页索引号小于总页数   
  128. return this.pageIndex < this.pageCount ;   
  129. }   
  130.   
  131. /**  
  132. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getHashPreviousPage()  
  133. */  
  134. public boolean getHashPreviousPage() {   
  135. //当前页索引号大于默认的初始页号,这里为1   
  136. return this.pageIndex > this.DEFAULT_PAGE_INDEX ;   
  137. }   
  138.   
  139.   
  140.   
  141. /**  
  142. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageCount()  
  143. */  
  144. public int getPageCount() {   
  145.   
  146. return this.pageCount;   
  147. }   
  148.   
  149.   
  150.   
  151. /**  
  152. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageSize()  
  153. */  
  154. public int getPageSize() {   
  155.   
  156. return this.pageSize;   
  157. }   
  158.   
  159. /**  
  160. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageRows()  
  161. */  
  162. public int getPageRows() {   
  163. //当页面大小为-1 时,返回总记录数   
  164. if(this.DEFAULT_PAGE_SIZE == this.pageSize ) {   
  165. return this.rows;   
  166. }   
  167.   
  168. //不为最后一页时,返回pageSize   
  169. if(!this.isLastPage()) {   
  170. return this.pageSize;   
  171. }   
  172. //最后一页时   
  173. return this.rows - (this.pageSize * (this.pageCount -1));   
  174. }   
  175.   
  176.   
  177.   
  178. /**  
  179. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageFirstRecord()  
  180. */  
  181. public int getPageFirstRecord() {   
  182.   
  183. //页大小为-1 时   
  184. if(this.DEFAULT_PAGE_SIZE== this.pageSize ) {   
  185. return 0;   
  186. }   
  187. return (this.pageIndex -1)* this.pageSize;   
  188. }   
  189.   
  190. /**  
  191. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageLastRecord()  
  192. */  
  193. public int getPageLastRecord() {   
  194. //页大小为-1时,返回总记录数   
  195. if(this.DEFAULT_PAGE_SIZE == this.pageSize) {   
  196. return this.rows;   
  197. }   
  198. return this.getPageFirstRecord() + this.getPageRows() ;   
  199. }    
  200. /**  
  201. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoFirstPage()  
  202. */  
  203. public void gotoFirstPage() {   
  204. this.gotoPage(this.DEFAULT_PAGE_INDEX);   
  205.   
  206. }   
  207.   
  208. /**  
  209. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoLastPage()  
  210. */  
  211. public void gotoLastPage() {   
  212. this.gotoPage(this.getPageCount());   
  213.   
  214. }   
  215.   
  216. /**  
  217. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoPreviousPage()  
  218. */  
  219. public void gotoPreviousPage() {   
  220. this.gotoPage(this.getPageIndex() -1);   
  221.   
  222. }    
  223.   
  224. /**  
  225. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoNextPage()  
  226. */  
  227. public void gotoNextPage() {   
  228. this.gotoPage(this.getPageIndex() + 1);   
  229.   
  230. }   
  231.   
  232. /**  
  233. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoPage(int)  
  234. */  
  235. public void gotoPage(int newPageIndex) {   
  236. if( newPageIndex >= this.DEFAULT_PAGE_INDEX && newPageIndex <= this.getPageCount() ) {   
  237. this.setPageIndex(newPageIndex);    
  238. }   
  239.   
  240. }   
  241. /**  
  242. * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#setPageSize(int)  
  243. */  
  244. public void setPageSize(int size) {   
  245. if(size < 1) {   
  246. size = 1;   
  247. }   
  248.   
  249. this.pageSize = size;   
  250.   
  251. //进行初始化   
  252. this.doInit();   
  253. }   
  254.   
  255. //-----------------------------------   
  256. //辅助方法   
  257. //-----------------------------------   
  258.   
  259.   
  260. /**  
  261. * 分页初始化方法,为了保证总是能正确的初始化,所以声明为final ,为了让子类可以调用声明为protected  
  262. *  
  263. */  
  264. protected final void doInit() {   
  265. int rows = 0;   
  266.   
  267. //获得总记录数   
  268. rows= totalRows();   
  269.   
  270. //设置总记录数   
  271. this.setRows(rows);   
  272. //设置新的总页数   
  273.   
  274. //计算并设置总页数   
  275. int pages = calculatePageCount();   
  276. this.setPageCount(pages);   
  277.   
  278. //转到第一页   
  279. this.gotoPage(this.DEFAULT_PAGE_INDEX);   
  280.   
  281. onInit();   
  282. }   
  283. /**  
  284. * 记算总页数  
  285. * @return 总页数  
  286. */  
  287. private int calculatePageCount() {   
  288.   
  289. //总记录数为0条,则返回的总页数为1   
  290. if(this.getRows() == 0) {   
  291. return this.DEFALT_PAGE_COUNT;   
  292. }   
  293.   
  294. //如果页面大小为-1,则返回的总页数为1   
  295. if(this.DEFAULT_PAGE_SIZE == this.getPageSize() ) {   
  296. return this.DEFALT_PAGE_COUNT;   
  297. }   
  298.   
  299. return this.getRows() / this.getPageSize() + ( this.getRows() % this.getPageSize() ==0 ? 0 :1);   
  300. }   
  301.   
  302.   
  303. /**  
  304. * 获得总记录数,调用queryTotalRows(),将异常封装为non-checked 异常  
  305. * @return 总记录数  
  306. * @throws ApplicationRuntimeException  
  307. */  
  308. private int totalRows() throws ApplicationRuntimeException{   
  309. try{   
  310. return queryTotalRows();   
  311. }   
  312. catch(Exception ex){   
  313. throw new ApplicationRuntimeException(ex);   
  314. }   
  315. }   
  316. /**  
  317. * 获得当前页数据,调用queryPageList()方法,将异常封装为non-checked异常  
  318. * @param startRow 开始记录号  
  319. * @param rowCount 记录总数  
  320. * @return 当前页数据  
  321. * @throws ApplicationRuntimeException  
  322. */  
  323. private List pageList(int startRow, int rowCount) throws ApplicationRuntimeException{   
  324. try{   
  325. return queryPageList(startRow, rowCount);   
  326. }catch(Exception ex){   
  327. throw new ApplicationRuntimeException(ex);   
  328. }   
  329. }   
  330.   
  331.   
  332. //-----------------------------------------   
  333. //子类实现的方法   
  334. //-----------------------------------------   
  335.   
  336. /**  
  337. * 初始化附加方法,由子类扩展  
  338. */  
  339. protected void onInit() {   
  340.   
  341. }   
  342.   
  343.   
  344. /**  
  345. * 查询获得总记录数,由子类具体实现  
  346. * @return 总记录数  
  347. * @throws Exception  
  348. */  
  349. protected abstract int queryTotalRows() throws Exception;   
  350.   
  351. /**  
  352. * 查询当前页数据,从startRow 开始的rowCount条记录  
  353. * @param startRow 开始记录号  
  354. * @param rowCount 记录总数  
  355. * @return 当前页数据  
  356. * @throws Exception  
  357. */  
  358. protected abstract List queryPageList(int startRow, int rowCount) throws Exception;   
  359.   
  360. }   
分享到:
评论
1 楼 qp7711 2011-01-18  
那这里是在哪里传参的?

相关推荐

Global site tag (gtag.js) - Google Analytics