锁定老帖子 主题:构建自己的通用分页组件(上)
该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-05-27
最后修改:2010-05-27
1. 需求:
2. 构建Page类:
public class Page { // 当前页面的页数 private int pageIndex; // 页面大小 private int pageSize; // 数据总量 private int totalData = -1; // 剩余数据量 private int surplusData; // 页面总量 private int totalPage; // 是否仅取第一页 private boolean firstPage; // 是否可以工作。默认为false,只有设置了数据总量才为true。 private boolean ready = false; } 该Page类包含了当前页数、每页的数据量、总数据量、剩余数据量、总页面量、是否仅取第一页以及该分页对象是否已经准备好,可以正常工作的标志。这样,调用者在调用后台业务方法进行分页查询数据时,只要构造一个指定当前页数pageIndex和页面大小pageSize的分页对象page,作为参数传递给后台业务方法即可。因此,根据实际需要,我们提供以下构造Page对象的构造方法: // 默认当前页面页数为第一页 private static final int DEFAULT_PAGE_INDEX = 1; // 默认页面大小为10 private static final int DEFAULT_PAGE_SIZE = 10; /** * 以默认当前页面和页面大小构造一个分页对象。 * 其中,默认当前页数为1,默认页面大小为10。 */ public Page() { this.pageIndex = DEFAULT_PAGE_INDEX; this.pageSize = DEFAULT_PAGE_SIZE; } /** * 以指定的当前页面页数和页面大小构造一个分页对象。 * @param pageIndex 当前页数,若参数值不大于0,则使用默认值1。 * @param pageSize 页面大小,若参数值不大于0,则使用默认值10。 */ public Page(int pageIndex, int pageSize) { this.pageIndex = pageIndex > 0 ? pageIndex : DEFAULT_PAGE_INDEX; this.pageSize = pageSize > 0 ? pageSize : DEFAULT_PAGE_SIZE; } /** * 以指定的页面大小构造一个表示第一页的分页对象。 * @param pageSize 页面大小,若参数值不大于0,则使用默认值10。 * @return 构造好的第一页分页对象。 */ public static Page newFirstPage(int pageSize) { Page page = new Page(1, pageSize); page.setFirstPage(true); page.setTotalData(pageSize); return page; } 无参构造方法Page()将构造一个默认当前为第1页,每页取10条数据的分页对象;Page(int pageIndex, int pageSize)可以构造一个指定当前页数和页面大小的分页对象;newFirstPage(int pageSize)为一静态方法,此方法可以以指定的页面大小构造一个表示只取第一页数据的分页对象,这种方式将不会计算数据总量和页面总量,出返回第一页的数据外,不做任何处理,以满足我们在一些首页只取前几条数据的需求。
3. 添加方法:
/** * 设置数据总量。在使用时,需提前调用此方法进行设置。 * 当数据总量设置好之后,会计算页面总量、修正当前页面页数、计算剩余数据量, * 并设置该分页对象已经准备好,可以正常工作。 * @param totalData 数据总量。 */ public void setTotalData(int totalData) { this.totalData = totalData; this.totalPage = this.totalData / pageSize + (this.totalData % pageSize == 0 ? 0 : 1); if (this.pageIndex > this.totalPage) { this.pageIndex = this.totalPage; } this.surplusData = this.totalData - (this.pageIndex - 1) * this.pageSize; this.ready = true; } 在设置完总数据量之后,分页对象page就能正常工作了。持久层在设置完数据总量后,必须取得当前要查询数据的起始行号和结束行号,以便对数据库进行分页查询。因此,我们在Page类中还必须提供获取当前分页的页面范围的方法,如下: /** * 获取当前分页对象的页面范围,包含当前页面的起始行和结束行。 * 如果未先调用setTotalData()方法设置数据总量,则会抛出运行时异常。 * @return 当前分页对象的页面范围。 * @throws java.lang.IllegalArgumentException 异常。 */ public PageScope getPageScope() throws IllegalArgumentException { if (!ready) { throw new IllegalArgumentException("Page has not seted data amount."); } if (this.pageIndex > this.totalPage) { return null; } PageScope scope = new PageScope(); int startLine = (this.pageIndex - 1) * this.pageSize; int endLine; if (this.surplusData < this.pageSize) { endLine = startLine + this.surplusData - 1; } else { endLine = startLine + this.pageSize - 1; } if (startLine < 0) { startLine = 0; } if (endLine < 0) { endLine = 0; } scope.setStartLine(startLine); scope.setEndLine(endLine); return scope; } PageScope类作为标识当前页面的页面范围信息。它只有两个属性:起始行号和结束行号。如下: public class PageScope { // 起始行号 private int startLine; // 结束行号 private int endLine; } 这样,后台业务方法通过对指定页面数据的分页查询和对时局总量的设定,把调用者所需要的页面数据和其他页面信息包装到page对象中返回,就实现了我们通用的分页需求。
public List<User> queryUsers(Page page) throws ServiceException; 调用者如果想查询第3页、每页查询15条用户信息,则可使用如下调用方式: Page page = new Page(3, 15); UserService userService = new UserServiceImpl(); List<User> usertList = userService.queryUser(page); 这样调用者就取到了第3页15条的用户信息,而且此时的page对象中,已经包含了其他页面的信息,包括总页数,总数据量等,我们可根据这些信息来展示其他页码。 Page page = Page.firstPage(5); List<User> usertList = userService.queryUser(page); 说明:
当不是分布式的应用时,前后台部署在同一个JVM上,这样通过前台传递的page对象的引用,后台设置好页面信息后,实际已经修改了前台传递的page对象,这样就不必再将page对象传回前台调用者。
5. 测试:
public class PageTest { /** * 测试构造一个仅表示第一页的分页对象。 */ @Test public void newFirstPage() { Page page = Page.newFirstPage(10); PageScope scope = page.getPageScope(); assertTrue(page.isFirstPage()); assertEquals(10, page.getTotalData()); assertEquals(1, page.getTotalPage()); assertEquals(1, page.getPageIndex()); assertEquals(10, page.getPageSize()); assertEquals(0, scope.getStartLine()); assertEquals(9, scope.getEndLine()); } /** * 测试构造一个指定当前页数和页面大小的分页对象。 */ @Test public void newPage() { Page page = new Page(2, 10); page.setTotalData(55); PageScope scope = page.getPageScope(); assertFalse(page.isFirstPage()); assertEquals(55, page.getTotalData()); assertEquals(6, page.getTotalPage()); assertEquals(2, page.getPageIndex()); assertEquals(10, page.getPageSize()); assertEquals(10, scope.getStartLine()); assertEquals(19, scope.getEndLine()); } }
6. 相关说明:
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-05-27
你看过springside吗?
|
|
返回顶楼 | |
发表时间:2010-05-27
caoyangx 写道 你看过springside吗? 只是大致了解,并未使用过,不知兄弟有何指教? |
|
返回顶楼 | |
发表时间:2010-05-27
lz讲解非常细致,清晰!赞一个
|
|
返回顶楼 | |
发表时间:2010-05-27
naily 写道 lz讲解非常细致,清晰!赞一个
谢谢~希望通过分享,大家共同进步。 |
|
返回顶楼 | |
发表时间:2010-05-27
代码没给完!
|
|
返回顶楼 | |
发表时间:2010-05-27
最后修改:2010-05-27
不知道 [下] 会不会有自定义的分页标签。。!!!
如果有的话,我期待看标签写的灵活性! |
|
返回顶楼 | |
发表时间:2010-05-27
xiangkun 写道 不知道 [下] 会不会有自定义的分页标签。。!!!
如果有的话,我期待看标签写的灵活性! 会有的,明天上... |
|
返回顶楼 | |
发表时间:2010-05-27
anzn20 写道 代码没给完!
代码我已打包上传上了,不知这位兄弟所说是何代码? |
|
返回顶楼 | |
发表时间:2010-05-27
zhangshixi 写道 anzn20 写道 代码没给完!
代码我已打包上传上了,不知这位兄弟所说是何代码? 最好发布能直接导入的 |
|
返回顶楼 | |