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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
说明:<br>一、含演示数据库建立脚本(较简单)<br>二、使用Struts、Hibernate和display超简单的实现分页,你不用在页面上再写很多<%%>和很多判断,简单到只需要几行语句:<br><html:form method="post" action="/displayList"><br> <display:table name="lst" cellspacing="0" border="1" cellpadding="0" requestURI="displayList.do" export="true"><br> <display:column property="id" title="编号" /><br> <display:column property="name" title="名字" /><br> <display:column property="age" title="年龄" /><br> </display:table><br> <pag:pagination name="pv" requestUri="displayList.do"></pag:pagination><br></html:form><br>这就是全部语句,不用写任何代码。<br>三、由于使用了display,所以自动实现了Excel | XML | CSV 的导出功能。<br>四、生成页面导航的样式是:<br>[首页/前一页] [后一页/尾页] 显示第1到1条 共3项 每页显示2项 共3页 第1页 GO<br>其中每页显示2项中的项操作人员可以随便改,“第1页”中的页号可以随便改,操作相当的灵活。我看到的样式暂只这一种,我想在display中应可以方便的改变导航样式,不行的话你就去修改display的标签源码,想改成什么样就改成什么样。<br><br>心得:<br>一、今天才明白使用Hibernate还有一个好处,你可以随便改数据库,你可以一会用oracle,一会用sqlserver,一会用mysql,总之你写成的代码换一种数据库,最多就是改一下那几个xml文件,个人感觉这才是java一个地方编写到处运行呢。<br>二、明白了使用标签的好处。<br><br>另提示一点:<br>打开测试用“http://localhost:8080/StrutsHibernateDisplay/displayList.do”,如果直接打开list.jsp会告诉你没有数据的。<br><br>代码是wenlong342的,我只是稍做修改,然后写了上面的说明文字。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值