TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
分页,这是Web应用中经常要涉及的问题,相信每一位开发人员都有这个自信解决这个问题,看了不少各式各样的分页实现代码,总觉得应该有一个比较好的规范来处理分页。有没有一个比较好、规范的分页接口,这样大家都可以围绕此接口做实现,这样分页处理就统一起来,简单多,而不我们看到现象:不同公司个人的不同版本的分页实现。
个人非常欣赏aopalliance项目,虽然只是一些接口的定义,但定于规范化AOP确实做出不小的贡献,不然不同的AOP实现的互通如何实现?规范的作用就发挥出来啦。 在Hibernate的站点上有一个分页的参考实现:
: http://www.hibernate.org/248.HTML
定义了分页处理所需的接口Page,这个接口非常不错,至少是我目前看到最完善和合理的(关于分页处理),将分页的信息全部包含啦,简单明了,代码如下:
[/code]
public
interface Page
{
boolean isFirstPage
(
);
boolean isLastPage
(
);
boolean hasNextPage
(
);
boolean hasPreviousPage
(
);
int getLastPageNumber
(
);
List getThisPageElements
(
);
Logger getLogger
(
);
int getTotalNumberOfElements
(
);
int getThisPageFirstElementNumber
(
);
int getThisPageLastElementNumber
(
);
int getNextPageNumber
(
);
int getPreviousPageNumber
(
);
int getPageSize
(
);
int getPageNumber
(
);
}
这里可能要做一些调整,个人觉得getLogger()没有必要放在这个接口中,它是用于处理日志的,这个可以在具体的实现代码完成,getThisPageElements()获取当前页的数据,这里返回为List类型数据,这里可能需要更改一下返回类型,当前页的数据可能涉及许多种类型:数组、RowSet、List等等,所以我们拟定将其返回值定为Object,在具体的代码中再去考虑究竟返回何种类型,所以这个接口修改后如下:
[/code]
public
interface Page
{
boolean isFirstPage
(
);
boolean isLastPage
(
);
boolean hasNextPage
(
);
boolean hasPreviousPage
(
);
int getLastPageNumber
(
);
Object getThisPageElements
(
);
int getTotalNumberOfElements
(
);
int getThisPageFirstElementNumber
(
);
int getThisPageLastElementNumber
(
);
int getNextPageNumber
(
);
int getPreviousPageNumber
(
);
int getPageSize
(
);
int getThisPageNumber
(
);
}
接口定义完毕后我们需要根据实际情况实现这个接口,这里主要讲三种情况:Hibernate的Query分页、Jdbc的ResultSet分页和List数据类型分页。在Hibernate的站点上提供了一个Hibernate分页的实现类HibernatePage,这个类处理从0开始,这可能与我们的实际情况不太一样,同时可能还有一些分页处理方面的bug,让我们看看HibernatePage的一个具体实现:
[/code]
/**
* Hibernate分页信息
*/
public
class HibernatePage
implements Page
{
private
List elements;
private
int pageSize;
private
int pageNumber;
private
int totalElements =
0;
/**
* 构建HibernatePage对象,完成Hibernate的Query数据的分页处理
*
* @param query Hibernate的Query对象
* @param pageNumber 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。
* 如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。
* 这两种情况将重新更改当前页的页码,为最后一页编码。
* @param pageSize 每一页显示的条目数
*/
public HibernatePage
(Query query,
int pageNumber,
int pageSize
)
{
this.
pageNumber = pageNumber;
this.
pageSize = pageSize;
try
{
ScrollableResults scrollableResults = query.
scroll
(
);
//get the total elements number
scrollableResults.
last
(
);
this.
totalElements = scrollableResults.
getRowNumber
(
);
if
(
Integer.
MAX_VALUE ==
this.
pageNumber ||
this.
pageNumber > getLastPageNumber
(
)
)
//last page
{
this.
pageNumber = getLastPageNumber
(
);
}
elements = query.
setFirstResult
(
(
this.
pageNumber -
1
) *
this.
pageSize
).
setMaxResults
(
this.
pageSize +
1
).
list
(
);
}
catch
(HibernateException e
)
{
throw
new
RuntimeException
(e
);
}
}
public
boolean isFirstPage
(
)
{
return getThisPageNumber
(
) ==
1;
}
public
boolean isLastPage
(
)
{
return getThisPageNumber
(
) >= getLastPageNumber
(
);
}
public
boolean hasNextPage
(
)
{
return getLastPageNumber
(
) > getThisPageNumber
(
);
}
public
boolean hasPreviousPage
(
)
{
return getThisPageNumber
(
) >
1;
}
public
int getLastPageNumber
(
)
{
return totalElements %
this.
pageSize ==
0 ? totalElements /
this.
pageSize : totalElements /
this.
pageSize +
1;
}
/**
* 返回List类型数据
*
* @return List数据源
*/
public
Object getThisPageElements
(
)
{
return elements;
}
public
int getTotalNumberOfElements
(
)
{
return totalElements;
}
public
int getThisPageFirstElementNumber
(
)
{
return
(getThisPageNumber
(
) -
1
) * getPageSize
(
) +
1;
}
public
int getThisPageLastElementNumber
(
)
{
int fullPage = getThisPageFirstElementNumber
(
) + getPageSize
(
) -
1;
return getTotalNumberOfElements
(
) < fullPage ? getTotalNumberOfElements
(
) : fullPage;
}
public
int getNextPageNumber
(
)
{
return getThisPageNumber
(
) +
1;
}
public
int getPreviousPageNumber
(
)
{
return getThisPageNumber
(
) -
1;
}
public
int getPageSize
(
)
{
return pageSize;
}
public
int getThisPageNumber
(
)
{
return pageNumber;
}
}
当然上述只是参考实现,你可以依据自己的分页算法进行实现,只要遵循这个接口即可。这里就不在给出List和ResultSet分页的实现逻辑,附件包含了源代码,大家可以参考一下。
总结:分页处理并不难,关键是没有一个好的接口和指导如何去实现的思想,这样造成了许多不规范,Hibernate站点上的Page接口设计的非常不错,同时给出了如何去实现的指导,相信有了一个规范接口和相关的实现逻辑,这样就分页处理就规范化多啦。
源码下载:http://file.javaxxz.com/2014/10/1/233315000.zip |
|