在Web应用开发中,不管是有没有数据库,经常要用到分页处理问题。EasyJWeb中通过引入IPageList接口来轻松解决我们的遇到的各种分页问题,包括对数据库记录分页、文件目录分页、数组或者Java对象分页等。
EasyJWeb作为一个Web框架,其MVC核心中本身没有包含分页的内容,我们这里所说的分页设计是指在EasyJWeb Tools业务引擎中关于分页需求应用的设计。
1、应用示例代码
首先们看看该分页设计的有关应用示例代码,该示例的完整代码可在 http://www.easyjf.com/download.htm中下载!
示例代码A:com.easyjweb.action.userManageAction.java
这是EasyJWeb文档中示例3(添删改查)中有关记录分页显示的部分代码:
public class userManageAction extends AbstractCrudAction {
public IPageList doQuery(WebForm form, int currentPage, int pageSize) {
....
DbPageList pList=new DbPageList(User.class,scope,paras);//通过调用DbPageList对象,返回分页结果IPageList
pList.doList(currentPage,pageSize);
return pList;
}
...
从代码中我们可以看出,这是一个对数库记录集对象的分页处理例子。直接通实现了IPageList接口的DbPageList类实现数据库的分页。
示例代码B:net.meybo.mail.action.EmailAction.java
这是MeyboMail Web邮件客户端开源简化版中,中对邮件主题进行分页显示的代码。
public class EmailAction implements IWebAction {
...
private Page doList(WebForm form, Module module,ActiveUser user)
{
...
List list=null;
...
list=EmailManage.getMailList(user.getUserName(),user.getServerDomain(),boxName);
IPageList pList=new PageList(new ListQuery(list));
if(pList!=null){
pList.doList(pageSize,currentPage,"","");
form.addResult("list",pList.getResult());
form.addResult("pages",new Integer(pList.getPages()));
form.addResult("rows",new Integer(pList.getRowCount()));
form.addResult("page",new Integer(pList.getCurrentPage()));
form.addResult("gotoPageHTML",CommUtil.showPageHtml(pList.getCurrentPage(),pList.getPages()));
}
...
上面例子中是对一个List集合进行分页,因为MeyboMail Web中没有用到数据库,所以使用ListQuery查询处理器进行处理。
2、EasyJWeb Tools中业务引擎中有关分页的接口及类
EasyJWeb Tools中通过使用IPageList及IQuery两个接口对分页问题进行抽象。
下面是IPageList接口的全部代码:
package com.easyjf.web.tools;
import java.util.Collection;
import java.util.List;
public interface IPageList {
public List getResult();//取回分页的结果
public void setQuery(IQuery q);//设置查询处理器
public int getPages();//返回总页数
public int getRowCount();//返回总记录数
public int getCurrentPage();//返回当前页
public void doList(int pageSize,int pageNo,String totalSQL,String queryHQL);//执行分页处理
public void doList(int pageSize,int pageNo,String totalSQL,String queryHQL,Collection paraValues);//执行分页处理
}
在IPageList中,我们看到通过设置查询处理器实现数据的查询及分页,这里我们在看看IQuery接口的内容:
package com.easyjf.web.tools;
import java.util.Collection;
import java.util.List;
public interface IQuery {
int getRows(String conditing);//得到总记录数
List getResult(String conditing);//根据条件查询并返回结果
void setFirstResult(int begin);//设置开始记录
void setMaxResults(int max);//设置每次查询返回的最大记录
void setParaValues(Collection paraValues);//设置查询参数值
List getResult(String conditing,int begin,int max);//从结果集中begin开始的位置,取max条记录
}
由此可见,我们的IPageList其实是通过设置调用不同的查询处理器实现对不同类型数据来进行分页处理的。
3、通用分页处理IPageList的实现PageList类
在EasyJWeb Tools中,我们的PageList类实现了IPageList接口,其是一个通用的分页处理类,其它各种类型数据的分页可以通过继承它来实现。
PageList.java的全部代码如下:
package com.easyjf.web.tools;
import java.util.*;
/**
* 实现通过调用IQuery实现分页处理
* @author 蔡世友
*
*/
public class PageList implements IPageList{
private int rowCount;//记录数
private int pages;//总页数
private int currentPage;//实际页数
private List result;
private IQuery query;
public PageList()
{
}
public PageList(IQuery q)
{
this.query=q;
}
public void setQuery(IQuery q)
{
query=q;
}
public List getResult()
{
return result;
}
public void doList(int pageSize, int pageNo, String totalSQL, String queryHQL) {
List rs=null;
int total=query.getRows(totalSQL);
if(total>0){
this.rowCount=total;
this.pages=(this.rowCount + pageSize - 1) / pageSize; //记算总页数
int intPageNo=(pageNo>this.pages?this.pages:pageNo);
if(intPageNo<1)intPageNo=1;
this.currentPage=intPageNo;
if(pageSize>0){
query.setFirstResult( (intPageNo - 1) * pageSize);
query.setMaxResults(pageSize);
}
rs=query.getResult(queryHQL);
}
result=rs;
}
public void doList(int pageSize, int pageNo, String totalSQL, String queryHQL,Collection paraValues) {
List rs=null;
query.setParaValues(paraValues);
int total=query.getRows(totalSQL);
if(total>0){
this.rowCount=total;
this.pages=(this.rowCount + pageSize - 1) / pageSize; //记算总页数
int intPageNo=(pageNo>this.pages?this.pages:pageNo);
if(intPageNo<1)intPageNo=1;
this.currentPage=intPageNo;
if(pageSize>0){
query.setFirstResult( (intPageNo - 1) * pageSize);
query.setMaxResults(pageSize);
}
rs=query.getResult(queryHQL);
}
result=rs;
}
public int getPages() {
return pages;
}
public int getRowCount() {
return rowCount;
}
public int getCurrentPage() {
return currentPage;
}
}
4、使用Hibernate访问数据库时的IQuery接口实现
这是EasyJF网站后台中,使用Hibernate中间件对数据库访问时候,其对应查询处理器IQuery接口的实现。
DbQuery.java的全部代码:
package com.easyjf.comm;
import java.util.Collection;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import com.easyjf.web.tools.IQuery;
public class DbQuery implements IQuery {
private Session session;
private int begin;
private int max;
private List paraValues;
public DbQuery(Session session)
{
this.session=session;
}
public void setParaValues(Collection paraValues) {
this.paraValues=(List)paraValues;
// System.out.println("参数":paraValues.size();)
}
public int getRows(String conditing) {
Query query1=session.createQuery(conditing);
if(paraValues!=null){
for(int i=0;i<paraValues.size();i++)
{
query1.setParameter(i,paraValues.get(i));
}
}
int total=((Integer)query1.uniqueResult()).intValue();
return total;
}
public List getResult(String conditing) {
Query query=session.createQuery(conditing);
if(paraValues!=null){
for(int i=0;i<paraValues.size();i++)
{
query.setParameter(i,paraValues.get(i));
}
}
if(begin>0)query.setFirstResult(begin);
if(max>0)query.setMaxResults(max);
return query.list();
}
public void setFirstResult(int begin) {
this.begin=begin;
}
public void setMaxResults(int max) {
this.max=max;
}
public List getResult(String conditing, int begin, int max) {
Query query=session.createQuery(conditing);
if(begin>0)query.setFirstResult(begin);
if(max>0)query.setMaxResults(max);
return query.list();
}
public void setParaValues(List paraValues) {
this.paraValues=paraValues;
}
}
5、对于List列表数据进行分页的查询处理器ListQuery实现
当我们要分页的目标数据不是数据库记录,而是其它储存方式时(如文本、xml或者内存中的实时对象线程等),可以转化为数组或List等。这时可通过使用ListQuery查询处理器实现分页查询。
ListQuery.java的全部代码:
package com.easyjf.web.tools;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ListQuery implements IQuery {
private int begin=0;
private int max=0;
private List list=null;
public ListQuery()
{
}
public ListQuery(List l)
{
if(l!=null){
this.list=l;
this.max=l.size();
}
}
public void initList(List l)
{
this.list=l;
this.max=l.size();
}
public int getRows(String conditing) {
return (list==null?0:list.size());
}
public List getResult(String conditing) {
return list.subList(begin,begin+max>list.size()?list.size():begin+max);
}
public void setFirstResult(int begin) {
this.begin=list.size()<begin?list.size():begin;
}
public void setMaxResults(int max) {
this.max=max;
}
public List getResult(String conditing, int begin, int max) {
return list;
}
public void setParaValues(Collection paraValues) {
// TODO Auto-generated method stub
}
}
6、关于分页的算法讨论
由于EasyJWeb Tools业务引擎是对众多分页需求的简单抽象。因此,无法对分页查询处理器的算法等作具体的限制,上面给出的两个查询处理器只是一个简单的应用实例,大家可以根据实际应用项目中的需求进行查询处理器的实现及算法设计。
由于水平有限,该设计上有很多不合理的地方,恳请大家指正!
7、EasyJWeb简介
EasyJWeb是基于java技术,应用于WEB应用程序快速开发的MVC框架,框架设计构思来源于国内众多项目实践,充分借签了当前主流的开源Web框架(Struts、JSF、Tapestry 、Webwork等),吸取了其优点及精华,利用Velocity作为模板页面引擎,是一个实现了页面及代码完全分离的MVC开发框架,是一个旨在于为中小型Web应用系统提供快速开发实践的简易Web框架。
EasyJF开源团队于2006年初才开始建设,因此当前整个开发团队组建以及所发布的作品,都显得极不成熟。EasyJWeb仍然处于测试阶段,请广大的Java爱好者多多批评及建议。同进也非常欢迎您能加入到我们的国产开源队伍中。
EasyJWeb官方网址: www.easyjf.com
EasyJF团队官方网址: www.easyjf.com