在JSF中实现分页(二)

前面一篇直接使用了Myfaces中的两个Component完成了一个简单的分页,这里将会介绍一种On-demand loading的方法来进行分页,仅仅在需要数据的时候加载。

     先来说一些题外话,为了实现这种方式的分页,公司里大约5-6个人做了半个多月的工作,扩展了dataTable,修改了dataScrollor,以及各种其他的方法,但是都不是很优雅。在上个月底的时候,在MyfacesMail List中也针对这个问题展开了一系列的讨论,最后有人总结了讨论中提出的比较好的方法,提出了以下的分页方法,也是目前实现的最为优雅的方法,也就是不对dataTabledataScrollor做任何修改,仅仅通过扩展DataModel来实现分页。

     DataModel 是一个抽象类,用于封装各种类型的数据源和数据对象的访问,JSFdataTable中绑定的数据实际上被包装成了一个DataModel,以消除各种不同数据源和数据类型的复杂性,在前面一篇中我们访问数据库并拿到了一个List,交给dataTable,这时候,JSF会将这个List包装成 ListDataModel dataTable访问数据都是通过这个DataModel进行的,而不是直接使用List

     接下来我们要将需要的页的数据封装到一个DataPage中去,这个类表示了我们需要的一页的数据,里面包含有三个元素:datasetSizestartRow,和一个用于表示具体数据的ListdatasetSize表示了这个记录集的总条数,查询数据的时候,使用同样的条件取count即可,startRow表示该页的起始行在数据库中所有记录集中的位置。

ExpandedBlockStart.gif ContractedBlock.gif /** */ /**
InBlock.gif * A simple class that represents a "page" of data out of a longer set, ie a
InBlock.gif * list of objects together with info to indicate the starting row and the full
InBlock.gif * size of the dataset. EJBs can return instances of this type when returning
InBlock.gif * subsets of available data.
ExpandedBlockEnd.gif 
*/

None.gif
public   class  DataPage
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
private   int  datasetSize;
InBlock.gif    
private   int  startRow;
InBlock.gif    
private  List data;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * Create an object representing a sublist of a dataset.
InBlock.gif     * 
InBlock.gif     * 
@param  datasetSize
InBlock.gif     *            is the total number of matching rows available.
InBlock.gif     * 
InBlock.gif     * 
@param  startRow
InBlock.gif     *            is the index within the complete dataset of the first element
InBlock.gif     *            in the data list.
InBlock.gif     * 
InBlock.gif     * 
@param  data
InBlock.gif     *            is a list of consecutive objects from the dataset.
ExpandedSubBlockEnd.gif     
*/

InBlock.gif    
public  DataPage( int  datasetSize,  int  startRow, List data)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this .datasetSize  =  datasetSize;
InBlock.gif        
this .startRow  =  startRow;
InBlock.gif        
this .data  =  data;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * Return the number of items in the full dataset.
ExpandedSubBlockEnd.gif     
*/

InBlock.gif    
public   int  getDatasetSize()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return  datasetSize;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * Return the offset within the full dataset of the first element in the
InBlock.gif     * list held by this object.
ExpandedSubBlockEnd.gif     
*/

InBlock.gif    
public   int  getStartRow()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return  startRow;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * Return the list of objects held by this object, which is a continuous
InBlock.gif     * subset of the full dataset.
ExpandedSubBlockEnd.gif     
*/

InBlock.gif    
public  List getData()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return  data;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}


 

     接下来,我们要对DataModel进行封装,达到我们分页的要求。该DataModel仅仅持有了一页的数据DataPage,并在适当的时候加载数据,读取我们需要页的数据。


 

ExpandedBlockStart.gif ContractedBlock.gif /** */ /**
InBlock.gif * A special type of JSF DataModel to allow a datatable and datascroller to page
InBlock.gif * through a large set of data without having to hold the entire set of data in
InBlock.gif * memory at once.
InBlock.gif * 


InBlock.gif * Any time a managed bean wants to avoid holding an entire dataset, the managed
InBlock.gif * bean should declare an inner class which extends this class and implements
InBlock.gif * the fetchData method. This method is called as needed when the table requires
InBlock.gif * data that isn't available in the current data page held by this object.
InBlock.gif * 


InBlock.gif * This does require the managed bean (and in general the business method that
InBlock.gif * the managed bean uses) to provide the data wrapped in a DataPage object that
InBlock.gif * provides info on the full size of the dataset.
ExpandedBlockEnd.gif 

*/
None.gif
public   abstract   class  PagedListDataModel  extends  DataModel
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int  pageSize;
InBlock.gif    
int  rowIndex;
InBlock.gif    DataPage page;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * Create a datamodel that pages through the data showing the specified
InBlock.gif     * number of rows on each page.
ExpandedSubBlockEnd.gif     
*/

InBlock.gif    
public  PagedListDataModel( int  pageSize)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
super ();
InBlock.gif        
this .pageSize  =  pageSize;
InBlock.gif        
this .rowIndex  =   - 1 ;
InBlock.gif        
this .page  =   null ;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * Not used in this class; data is fetched via a callback to the fetchData
InBlock.gif     * method rather than by explicitly assigning a list.
ExpandedSubBlockEnd.gif     
*/

InBlock.gif
InBlock.gif    
public   void  setWrappedData(Object o)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
if (o  instanceof  DataPage)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this .page  =  (DataPage) o;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
else
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw   new  UnsupportedOperationException( " setWrappedData " );
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public   int  getRowIndex()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return  rowIndex;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * Specify what the "current row" within the dataset is. Note that the
InBlock.gif     * UIData component will repeatedly call this method followed by getRowData
InBlock.gif     * to obtain the objects to render in the table.
ExpandedSubBlockEnd.gif     
*/

InBlock.gif
InBlock.gif    
public   void  setRowIndex( int  index)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        rowIndex 
=  index;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * Return the total number of rows of data available (not just the number of
InBlock.gif     * rows in the current page!).
ExpandedSubBlockEnd.gif     
*/

InBlock.gif
InBlock.gif    
public   int  getRowCount()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return  getPage().getDatasetSize();
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * Return a DataPage object; if one is not currently available then fetch
InBlock.gif     * one. Note that this doesn't ensure that the datapage returned includes
InBlock.gif     * the current rowIndex row; see getRowData.
ExpandedSubBlockEnd.gif     
*/

InBlock.gif    
private  DataPage getPage()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
if  (page  !=   null )
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return  page;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
int  rowIndex  =  getRowIndex();
InBlock.gif        
int  startRow  =  rowIndex;
InBlock.gif        
if  (rowIndex  ==   - 1 )
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//  even when no row is selected, we still need a page
InBlock.gif            
//  object so that we know the amount of data available.
InBlock.gif
            startRow  =   0 ;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
//  invoke method on enclosing class
InBlock.gif
        page  =  fetchPage(startRow, pageSize);
InBlock.gif        
return  page;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8485249/viewspace-429910/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/8485249/viewspace-429910/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值