一个分页标签开发

本文主要说的是关于在展示层一些常用的方案和实现,目录如下:
  手工实现分页
  • 用eXtremeTable标签实现自动分页
  • 用oscache缓存jsp,提高性能
第一.自己实现一个工具类PageBean完成所有分页工作.

本分页实现概览:Struts + hibernate
PageBean负责两部分内容,一是要在页面显示的业务信息,是一个ArrayList;另一个是逻辑控制信息,诸如是否有下一页,上一页等等.
PageBean代码如下:
<!----> public  class  PageBean {
  
int  currentPage  =  1 ; // 当前页:Action控制
   int  totalPages  =  0 ; // 总页数 :自己运算
   int  pageRecorders  =  5 // 每页记录数,默认为5,可以在初始化的时候修改 // 总数据数
   int  pageStartRow  =  0 // 每页的起始数
   int  pageEndRow  =  0 // 每页显示数据的终止数
   boolean  hasNextPage  =  false // 是否有下一页:自己运算
   boolean  hasPreviousPage  =  false // 是否有前一页 :自己运算
  List objList  =  new  ArrayList(); // 存放欲展示的对象列表
   int  totalRows; // 总记录数,由底层service提供

  
// 是否有上一页
   public  boolean  isHasPreviousPage() {
    
return  (currentPage  >  1 ? true : false  );
  }

  
// 共有多少页,service只提供有多少条记录,多少页数由PageBean自己运算
   public  int  getTotalPages() {
    
return  (totalRows / pageRecorders  == 0 ? totalRows / pageRecorders:totalRows / pageRecorders + 1 );
  }

  
public  int  getCurrentPage() {
    
return  currentPage;
  }

  
public  int  getPageEndRow() {
    
return  pageEndRow;
  }

  
// 是否有下一页
   public  boolean  isHasNextPage() {
    
return  (currentPage  <  this .getTotalPages()  ?  true : false );
  }

  
public  int  getTotalRows() {
    
return  totalRows;
  }

  
public  int  getPageStartRow() {
    
return  pageStartRow;
  }

  
public  int  getPageRecorders() {
    
return  pageRecorders;
  }

  
public  void  setObjList(List objList) {
    
this .objList  =  objList;
  }

  
public  void  setHasPreviousPage( boolean  hasPreviousPage) {
    
this .hasPreviousPage  =  hasPreviousPage;
  }

  
public  void  setTotalPages( int  totalPages) {
    
this .totalPages  =  totalPages;
  }

  
public  void  setCurrentPage( int  currentPage) {
    
this .currentPage  =  currentPage;
  }

  
public  void  setPageEndRow( int  pageEndRow) {
    
this .pageEndRow  =  pageEndRow;
  }

  
public  void  setHasNextPage( boolean  hasNextPage) {
    
this .hasNextPage  =  hasNextPage;
  }

  
public  void  setTotalRows( int  totalRows) {
    
this .totalRows  =  totalRows;
  }

  
public  void  setPageStartRow( int  pageStartRow) {
    
this .pageStartRow  =  pageStartRow;
  }

  
public  void  setPageRecorders( int  pageRecorders) {
    
this .pageRecorders  =  pageRecorders;
  }

  
public  List getObjList() {
    
return  objList;
  }

  
public  PageBean() {}


  
public  void  description() {

    String description 
=  " 共有数据数: "  +  this .getTotalRows()  +

        
" 共有页数:  "  +  this .getTotalPages()  +

        
" 当前页数为: "  +  this .getCurrentPage()  +

        
"  是否有前一页:  "  +  this .isHasPreviousPage()  +

        
"  是否有下一页: "  +  this .isHasNextPage()  +

        
"  开始行数: "  +  this .getPageStartRow()  +

        
"  终止行数: "  +  this .getPageEndRow();

    System.out.println(description);
  }
}

注意,我没有在PageBean里放具体的业务逻辑,诸如getBooks()等,目的很简单,具有通用性,业务逻辑由另一个业务类实现BookService,BookService获得的业务数据都放在了PageBean的ArrayList里.

BookService代码如下:
<!----> public  class  BookService {
  
private  static  Logger log  =  Logger.getLogger(BookService. class .getName());
  
public  BookService() {
  }

  
/**
   * 获得book列表
   * 
@param  pageBean PageBean:返回的对象存在pageBean里
   
*/
  
public  static  void  getBooks(PageBean pageBean) {
    String infoSql 
=  " from Book " ; // 获得业务信息
    String countSql  =  " select count(*) from Book " ; // 获得控制信息
    Session session  =  null ;
    
try  {
      session 
=  DBUtil.currentSession();
      Query query 
=  session.createQuery(infoSql);
      query.setFirstResult((pageBean.getCurrentPage()
- 1 ) *  pageBean.getPageRecorders()); // 起始页
      query.setMaxResults(pageBean.getPageRecorders()); // 每页记录数
      pageBean.getObjList().clear();
      
for  (Iterator it  =  query.iterate(); it.hasNext(); ) {
        Book po 
=  (Book)it.next();
        BookVo vo 
=  new  BookVo();
        BeanUtils.copyProperties(vo,po);
        pageBean.getObjList().add(vo);
      }
      session 
=  DBUtil.currentSession();
      query 
=  session.createQuery(countSql);
      
int  totalRecords  =  ((Integer)query.list().get( 0 )).intValue();
      pageBean.setTotalRows(totalRecords);
    }
    
catch  (Exception e) {
      e.printStackTrace();
      System.out.println(
" 数据库异常 "  +  e.toString());
    }
    
finally  {
      
try  {
        
if  ( null  !=  session) {
          session.close();
        }
      }
      
catch  (HibernateException ex) {
        ex.printStackTrace();
      }
    }

  }


}

在Struts的Action中调用service,返回一个PageBean给展示页面
Action代码如下:
<!---->  1  public  class  PageListAction  extends  Action {
 2 
 3     public  PageListAction() {}
 4 
 5    ArrayList arrayList  =  new  ArrayList();
 6 
 7     public  ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response)  throws  Exception {
 8      String action;
 9      PageBean pageBean  =  null ;
10      action  =  request.getParameter( " action " );
11       if (action  ==  null  ||  action.equals( " null " )) {  // 第一次读取数据
12        pageBean  =  new  PageBean();
13      }  else  { // 用户选择上一页或者下一页
14         if (action  ==  " nextPage "  ||  action.equals( " nextPage " )) {
15          pageBean  =  (PageBean)request.getSession().getAttribute( " pageBean " );
16          pageBean.setCurrentPage(pageBean.getCurrentPage() + 1 );
17        } else  if (action  ==  " previousPage "  ||  action.equals( " previousPage " )) {
18          pageBean  =  (PageBean)request.getSession().getAttribute( " pageBean " );
19          pageBean.setCurrentPage(pageBean.getCurrentPage() - 1 );
20        } else  if (action  ==  " targetPage "  ||  action.equals( " targetPage " )){ // 指定页
21          pageBean  =  (PageBean)request.getSession().getAttribute( " pageBean " );
22          System.out.println( " targetPage= "  +  request.getParameter( " targetPage " ));
23           // 这里根据需要可以对填写的目标页进行判断,不要大于最大页数[此处省略]
24          pageBean.setCurrentPage(Integer.parseInt(request.getParameter( " targetPage " )));
25        }
26      }
27       if ( null  ==  pageBean)  throw  new  Exception( " 获得PageBean异常 " );
28      BookService service  =  new  BookService();
29      service.getBooks(pageBean);
30      pageBean.description();
31      request.getSession().setAttribute( " pageBean " ,pageBean);
32      request.setAttribute( " result " ,pageBean.getObjList());
33       return (mapping.findForward( " success " ));
34    }
35  }

在本Action中判断了可能出现的三种情况:
  1. 用户选择了"上一页"
  2. 用户选择了"下一页"
  3. 用户手工输入了指定的某一页
这里有点感觉不爽的是必须hard coding,但是不这么做感觉暂时也想不出什么好的办法来,毕竟一个PageBean不可能封装所有的细节,如果你有更好的方式请指点哦 :)

好了,到了我们呼之欲出的展示页面了 :)
show.jsp代码如下
<!----> <% @ taglib uri = " /WEB-INF/struts-logic.tld "  prefix = " logic "  %>
<% @ taglib uri = " /WEB-INF/struts-bean.tld "  prefix = " bean "  %>
<% @ taglib uri = " /WEB-INF/struts-html.tld "  prefix = " html "  %>
<% @ page contentType = " text/html; charset=gb2312 "  language = " java " %>

< html:html  locale ="true" >
< head >
< meta  http-equiv ="Content-Type"  content ="text/html; charset=gb2312" >
  
< script  language ="javaScript" >
    
function  go(){
      
try {
      
var  targetValue  =  document.getElementById( " targetPage " ).value;
      parseInt(targetValue);
      alert(targetValue);
      }
catch (e){
        alert(
" 请正确填写目标页 " );
        
return ;
      }
      
if (targetValue  ==  null  ||  targetValue  ==  ''){
        alert(
" 请填写目标页 " );
        
return ;
      }
      window.location 
=  " //pageList.do?action=targetPage&targetPage= " + targetValue;
    }
  
</ script >
</ head >
< body >
< logic:present  name ="pageBean" >
  共有数据总数
< bean:write  name ="pageBean"  property ="totalRows" /> ;
共分
< bean:write  name ="pageBean"  property ="totalPages" /> 页,
当前是第
< bean:write  name ="pageBean"  property ="currentPage" />
</ logic:present >
< table  border ="1" >
< tr >< th > 书名 </ th >< th > 作者 </ th >< th > 价格 </ th ></ tr >
    
< logic:present  name ="result" >
        
< logic:iterate  id ="book"  name ="result" >
        
< logic:present  name ="book" >
        
< tr >
           
< td >< bean:write  name ="book"  property ="name"  /></ td >
           
< td >  < bean:write  name ="book"  property ="author"  /></ td >
           
< td >< bean:write  name ="book"  property ="price"  /></ td >
        
/ tr >
        
</ logic:present >
        
</ logic:iterate >
    
</ logic:present >
</ table >
< logic:present  name ="pageBean" >
< logic:equal  name ="pageBean"  property ="hasNextPage"  value ="true" >
    
< html:link  page ="/pageList.do?action=nextPage" > nextPage </ html:link >
</ logic:equal >
< logic:equal  name ="pageBean"  property ="hasPreviousPage"  value ="true" >
    
< html:link  page ="/pageList.do?action=previousPage" > PreviousPage </ html:link >
</ logic:equal >
< input  type ="text"  name ="targetPage"  id ="targetPage" />
< input  type ="button"  value ="go!"  size ="2"  onclick ="go();" />
</ logic:present >
</ body >
</ html:html >

是否有上一页或者下一页,全部根据PageBean里的逻辑值动态判断.
这个页面没什么可说的,你可以根据自己的情况调整就OK了


第二. 用eXtremeTable标签实现自动分
上面的方案大家已经看出来了,实际上是每一次用户点击一个页面都会查询数据库,这可以算是既是优点也是缺点,优点是数据库不用一次查询出所有的数据,在高数据量的情况下尤其如此,缺点就是和数据库的交互次数有点多了,不过这个完全看你的业务策略了,如果用户大多数情况下就是看没几条的记录,你又何必把全部数据给他取出来呢? 当然,在这里我们就说说一次取出全部数据,然后让标签帮助我们自动分页,终于可以偷懒了,你所要做的仅仅是取出所需要的业务数据而已,其他的就交给eXtremeTable标签来完成就OK了.
eXtremeTable标签的下载,安装和文档请参看 官方网站
<!----> public  static  List getBooks() {
    log.debug(
" execute getBooks method! " );
    String infoSql 
=  " from Book " ; // 获得业务信息
    Session session  =  null

你可能感兴趣的:(html,Hibernate,bean,jsp,struts)