07-06
26

Struts分页的多个实现 (后台分页)

Struts分页的一个实现

在Web应用程序里,分页总让我们开发人员感到很头疼,倒不是因为技术上有多么困难,只是本来和业务没有太多关系的这么一个问题,你却得花不少功夫来处理。要是稍不留神,时不时出点问题就更郁闷了。我现在做的一个项目也到了该处理分页的时候了,感觉以前处理得都不好,所以这次有所改变,基本目标是在现有(未分页)的代码基础上,尽量少做修改,并且同样的代码可以应用于不同模块的分页。以下就是我用的方法:
首先,考虑分页绝大多数发生在列表时,组合查询时也需要用到。在我的项目里,列表的Action一般名字为ListXXXActioin,例如客户列表是ListClientsAction等等。在未分页前,ListXXXAction里会把所有的对象取出,通过request.setAttribute()放在request里,然后将请求转向到列表的jsp(例如listClients.jsp)显示出来(你可能会说不要在Action里放业务逻辑,但现在这不是我们考虑的重点)。而分页后,我们只取用户请求页对应的那些对象。为了最大限度的达到代码重用,我做了以下工作:
1、新建一个Pager类,该类有beginPage、endPage、currentPage、pageSize和total等int类型的属性,分别代表开始页、结束页、当前页、每页记录数和总记录数,它主要是让jsp页面显示页导航使用的。请注意currentPage属性是从0开始的。
2、新建一个AbstractListActioin类,并让所有ListXXXAction都继承它。在这个类里覆盖execute()方法,可以在这里判断权限等等,并在判断权限通过后执行一个abstract的act()方法,这个act()由ListXXXAction来实现。
3、在AbstractListAction里增加getPage()方法,用来从request得到用户请求的页码(若未请求则认为是第0页):
protected int getPage(HttpServletRequest request) {
    String p 
= request.getParameter("p");
    
if (p == null)
        
return 0;
    
else
        
try {
            
return Integer.parseInt(p);
        } 
catch (NumberFormatException e) {
            
return 0;
        }
}
 
4、在AbstractListAction里增加makePager()方法,用来向request里增加一个Pager类的实例,供jsp页面显示页导航:
protected Pager makePager(HttpServletRequest request, int total) {
    Pager pager
=new Pager();
    pager.setTotal(total);
    pager.setPageSize(Config.getInstance().getPageSize());
    pager.setBeginPage(
0);
    pager.setEndPage(((pager.getTotal()) 
- 1/ pager.getPageSize() + 1);
    pager.setCurrentPage(getPage(request));
    
return pager;
}
 
注意在我的项目里,每页记录数是写在配置文件里的,如果你没有配置文件,上面第4行setPageSize()的参数直接填数字即可,例如pager.setPageSize(10);
5、这样,所有的ListXXXAction都可以使用getPage()得到请求的页码,并且能够方便的通过makePager()构造需要放在request里的pager对象了。现在要在从数据库取数据的代码上再做一些修改,即只取所需要的那一部分数据。由于我的项目中使用了Hibernate,所以这个修改也不是很困难。未分页前,在我的ListClientsAction里是通过构造一个Query来得到全部Client的,现在,只要在构造这个Query后再加两句(setMaxResults和setFirstResult)即可:
Query query =  ;//构造query的语句 
int total =  ;//得到总记录数 
Pager pager = makePager(request, total);//调用父类中的方法构造一个Pager实例
query.setMaxResults(pager.getPageSize());//设置每页记录数
query.setFirstResult(pager.getCurrentPage() * pager.getPageSize()); //设置开始位置
request.setAttribute(Pager.class.getName(), pager);//把pager放在request里
request.setAttribute(Client.class.getName(), query.list());
目前存在一个问题,就是在上面代码的第二句中,应该是获得总记录数,但我暂时没有特别好的办法不得到全部对象而直接得到记录数,只能很恐怖的用“int total = query.list().size();”,汗……
6、最后,我写了一个页导航的jsp页面pager.jsp,供各个显示列表的jsp来include,代码如下:
<%Pager pager=(Pager)request.getAttribute(Pager.class.getName());%>
<table width="90%" border="0" align="center" cellpadding="2" cellspacing="1" bgcolor="#CCCCCC">
<tr>
    
<td bgcolor="#EEEEEE" align="right">
    
<bean:message key="prompt.pager" arg0="<%=""+pager.getTotal()%>"/>
        [
<%
String url
=request.getRequestURL().toString();
for(int i=pager.getBeginPage();i<pager.getEndPage();i++){
    
if(i==pager.getCurrentPage()){
    
%>
        
<%=(i+1)%>
    
<%}else{
        String qs
=request.getQueryString()==null?"":request.getQueryString();
        String op 
= "p="+pager.getCurrentPage();//Original page parameter expression
        String np = "p="+i;//New expression
        if(qs.indexOf(op)==-1)
            qs
=np+"&"+qs;
        qs
=qs.replaceAll(op,np);
        
%>
        
<a href="<%=url+"?"+qs%>"><%=(i+1)%></a>
    
<%}%>
    
<%if(i<pager.getEndPage()-1){%>
    
&nbsp;
    
<%}%>
<%}%>
]
</td></tr>
</table>
我觉得有必要解释一下,在上面的代码中,关于每一页对应的url是这样处理。取request.getRequestURL().toString()和request.getQueryString(),其中前者是不需要变的,而后者中可能包含“q=2”这样的页码请求也可能不包含即缺省请求第0页,所以统一用replaceAll()方法将其去掉,然后将对应的页码请求串(如“q=3”)加在qs的前面。这样做的好处是,每个模块都可以使用这个页导航,并且不会丢失url中的其他参数(例如今后加入排序功能后,url中可能包含“dir=desc”这样的参数)。
在列表jsp(listClients.jsp)中,很简单的这样include它(之所以要放在<logic:notEmpty>里,是希望在没有记录可显示的时候就不显示页导航了):
<logic:notEmpty name="<%=Client.class.getName()%>">
    
<%@include file="/pager.jsp"%>
</logic:notEmpty>
经过上面几步的处理,我的客户列表已经可以实现分页了,效果见下图。如果在另外一个模块中也需要分页,比如部门列表时,只需要1、修改ListDeptsAction继承AbstractListAction,2、在ListDeptsAction里增加setMaxResults()和setFirstResults()方法,3、在listDepts.jsp中适当的位置include页导航,就可以了,改动是相当小的。
 
最后,如果希望组合查询的结果也能够分页,必须指定组合查询表单的method属性为“GET”,这样查询要求会被记录在url中,分页导航从而能够正常的工作(每次换页都将查询要求和请求的页码提交)。


在struts中分页的一种实现
我的项目中的分页功能
1, 思路
 
使用一个页面控制类,它记录页面信息,如上页,下页,当前页等。在查询的Action中,将这个控制类和查询条件一起传递给数据库访问bean,然后将这两个参数保存在用户session中。在分页控制Action中,利用接收到的分页参数调用数据库访问的bean.
 
 
2,实现
 
(1)分页控制类
/* @author nick
 * Created on 2004-3-18
 * file name:PageController.java
 *
 *
 */
package com.tower.util;
 
/**
 * @author nick
 * 2004-3-18
 * 用来进行翻页控制
 *
 */
public class PageController {
    int totalRowsAmount; //总行数
    boolean rowsAmountSet; //是否设置过totalRowsAmount
    int pageSize=2;   //每页行数
    int currentPage=1; //当前页码
    int nextPage;
    int previousPage;
    int totalPages; //总页数
    boolean hasNext; //是否有下一页
    boolean hasPrevious; //是否有前一页
    String description;
    int pageStartRow;
    int pageEndRow;
   
    public PageController(int totalRows){
        setTotalRowsAmount(totalRows);
    }
    public PageController(){}
   
 
 
 
 
    /**
     * @param i
     * 设定总行数
     */
    public void setTotalRowsAmount(int i) {
        if(!this.rowsAmountSet){
           totalRowsAmount = i;
           totalPages=totalRowsAmount/pageSize+1;
           setCurrentPage(1);
           this.rowsAmountSet=true;
       }
      
    }
 
    /**
     * @param i
     *
     * 当前页
     *
     */
    public void setCurrentPage(int i) {
        currentPage = i;
        nextPage=currentPage+1;
        previousPage=currentPage-1;
       //计算当前页开始行和结束行
        if(currentPage*pageSize<totalRowsAmount){
           pageEndRow=currentPage*pageSize;
           pageStartRow=pageEndRow-pageSize+1;
          
        }else{
           pageEndRow=totalRowsAmount;
           pageStartRow=pageSize*(totalPages-1)+1;
       }
      
      
       //是否存在前页和后页
      
       if (nextPage>totalPages){
           hasNext=false;
        }else{
           hasNext=true;
       }
        if(previousPage==0){
          hasPrevious=false;
        }else{
           hasPrevious=true;
       };
        System.out.println(this.description());
    }
 
    /**
     * @return
     */
    public int getCurrentPage() {
        return currentPage;
    }
 
    /**
     * @return
     */
    public boolean isHasNext() {
        return hasNext;
    }
 
    /**
     * @return
     */
    public boolean isHasPrevious() {
        return hasPrevious;
    }
 
    /**
     * @return
     */
    public int getNextPage() {
        return nextPage;
    }
 
    /**
     * @return
     */
    public int getPageSize() {
        return pageSize;
    }
 
    /**
     * @return
     */
    public int getPreviousPage() {
        return previousPage;
    }
 
    /**
     * @return
     */
    public int getTotalPages() {
        return totalPages;
    }
 
    /**
     * @return
     */
    public int getTotalRowsAmount() {
        return totalRowsAmount;
    }
 
    /**
     * @param b
     */
    public void setHasNext(boolean b) {
        hasNext = b;
    }
 
    /**
     * @param b
     */
    public void setHasPrevious(boolean b) {
        hasPrevious = b;
    }
 
    /**
     * @param i
     */
    public void setNextPage(int i) {
        nextPage = i;
    }
 
    /**
     * @param i
     */
    public void setPageSize(int i) {
        pageSize = i;
    }
 
    /**
     * @param i
     */
    public void setPreviousPage(int i) {
        previousPage = i;
    }
 
    /**
     * @param i
     */
    public void setTotalPages(int i) {
        totalPages = i;
    }
    /**
     * @return
     */
    public int getPageEndRow() {
        return pageEndRow;
    }
 
    /**
     * @return
     */
    public int getPageStartRow() {
        return pageStartRow;
    }
 
    public String getDescription(){
       String description="Total:"+this.getTotalRowsAmount()+
       " items "+this.getTotalPages() +" pages";
//    this.currentPage+" Previous "+this.hasPrevious +
//    " Next:"+this.hasNext+
//    " start row:"+this.pageStartRow+
//    " end row:"+this.pageEndRow;
       return description;
    }
   
    public String description(){
       String description="Total:"+this.getTotalRowsAmount()+
       " items "+this.getTotalPages() +" pages,Current page:"+
       this.currentPage+" Previous "+this.hasPrevious +
       " Next:"+this.hasNext+
       " start row:"+this.pageStartRow+
       " end row:"+this.pageEndRow;
      return description;
    }
   
   
    public static void main(String args[]){
        PageController pc=new PageController(3);
        System.out.println(pc.getDescription());
//        pc.setCurrentPage(2);
//     System.out.println(pc.description());
//     pc.setCurrentPage(3);
//     System.out.println(pc.description());
    }
 
 
}
 
2)查询Action的代码片断
 
    public ActionForward execute(
        ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception {
       Base queryForm= (Base) form;
          
        if(!queryForm.getName().equals("")){
           PageController pc=new PageController();       
            EmployeeBase service=new EmployeeBase();      
            ArrayList result=(ArrayList)service.search(queryForm,pc);
          
            HttpSession session=request.getSession();
           
           session.setAttribute("queryForm",queryForm);
            session.setAttribute("pageController",service.getPageController());
          
            request.setAttribute("queryResult",result);   
           request.setAttribute("pageController",service.getPageController());       
           return mapping.findForward("haveResult");
        }else{
           return mapping.findForward("noResult");
        }
      
      
      
   
    }
 
3),翻页Action的代码片断
 
public ActionForward execute(
        ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception {
   
          
        //读取翻页参数
              
        TurnPageForm turnPageForm=(TurnPageForm)form;
      
       //PageController中取出查询信息,并使用bean提供的调用接口处理结果
        
        HttpSession session=request.getSession();
        PageController pc=(PageController)session.getAttribute("pageController");    
       Base queryForm=(Base)session.getAttribute("queryForm");
      
   
        pc.setCurrentPage(turnPageForm.getViewPage());
      
        EmployeeBase service=new EmployeeBase();
      
        ArrayList result=(ArrayList)service.search(queryForm,pc);
      
       //根据参数将数据写入 request
      
        request.removeAttribute("queryResult");
        request.removeAttribute("pageController");
        request.setAttribute("queryResult",result);   
        request.setAttribute("pageController",pc);
              
        //forward 到显示页面
      
      
      
        return mapping.findForward("haveResult");
      
      
      
      
   
    }
 
4)数据库访问bean中的片断
 
public Collection search(Base base, PageController pc)
        throws SQLException {
        ArrayList emps = new ArrayList();
        ResultSet rs = getSearchResult(base);
 
        rs.absolute(-1);
        pc.setTotalRowsAmount(rs.getRow());
        setPageController(pc);
       if (rs.getRow() > 0) {
 
           rs.absolute(pc.getPageStartRow());
 
 
           do {
               System.out.println("in loop" + rs.getRow());
 
               Base b = new Base();
               b.setName(rs.getString("Name"));
               b.setIdCard(rs.getString("IDCard"));
               System.out.println("From db:" + rs.getString("IDCard"));
               emps.add(b);
               if (!rs.next()) {
                   break;
               }
           } while (rs.getRow() < (pc.getPageEndRow() + 1));
       }
        return emps;
    }
 
 
(5)jsp中,翻页部分的代码片断
 
<bean:write name="pageController" property="description"/>
      
        <logic:equal name="pageController" property="hasPrevious" value="true">
              <a href="turnPage.do?viewPage=<bean:write name="pageController" property="previousPage"/>" class="a02">
                Previous
             </a>
        </logic:equal>
 
        <logic:equal name="pageController" property="hasNext" value="true">
          <a href="turnPage.do?viewPage=<bean:write name="pageController" property="nextPage"/>" class="a02">
          Next
          </a>
        </logic:equal>
 
 
 
这样一来,翻页的功能可以以你喜欢的方式表现给client


文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: 分页
相关日志:
评论: 0 | 引用: 0 | 查看次数: 938
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭