Struts + Hibernate分页显示 v1.0

Struts + Hibernate分页显示 v1.0

2007年8月5日更新:
这篇写于2年前的拙文,没想到现在还有很多的访问量,感谢大家的支持,很多朋友来信询问HibernateDAO的代码,实际上HibernateDAO是Hibernate应用的一种很流行的模式,在网上很容易就查到,所以我就没有列到文章里,但为了方便大家,我提供一个链接供参考:
http://www.javaeye.com/article/122

这篇文章是hibernate 2.0的版本,对于现在3.0版本改动不多,只需改一下包名:org.hibernate
题外话:关于hibernate, spring, struts等等j2ee开发框架,个人建议如果有时间的话,大家可以研究一下jboss  seam这个下一代JavaEE开发框架,非常的值得

另外我的blog已经全部迁至javaeye, http://jeffreyhsu.javaeye.com  这里不做更新
欢迎大家访问

这是我学习Struts半个月以来,在开发第一个留言簿的时候,参考了网上很多的方案,然后做的一套Web分页机制,使用StrutsMVC方式,利用Hibernate的分段查询的机制来实现,JSP页面干净不含Java代码,逻辑结构清晰,易于扩展。是一个比较好的完整的分页解决方案。

 

目前为第一个版本,以后会逐步完善,在这里希望能起到一个抛砖引玉的作用

大家有什么好的建议可以与我联系:

jeffreyxu@gmail.com

 

阅读门槛:

Java基础知识

Struts基础知识

Hibernate有一定了解

 

一、         开发环境

Tomcat 5.5.7

Eclipse 3.0.2

SQLServer2000

Hibernate

二、         开发思路

 

分页的步骤:

按照Struts MVC处理方式,对于显示数据的请求要先提交至相应的Action(这里是DisplayAction)进行处理,查询数据库,根据数据总数初始化分页信息,然后从数据库取得第一页所要显示的数据(这里并没有全部一次查询所有数据,效率较高),然后转交至相应的显示页面显示。

 

三、         源码部分

1)        Hibernate 部分:

 

HibernateUtil  Hibernate实用类,负责Session的取得和关闭

 

/*

 * @(#)HibernateUtil.java    2005-4-26

 *

 * Copyright (c) 2005, Jeffrey Hsu

 */

import net.sf.hibernate.*;

import net.sf.hibernate.cfg.*;

 

 

public class HibernateUtil {

    private static final SessionFactory sessionFactory;

 

    static {

        try {

            sessionFactory = new Configuration().configure()

                                                .buildSessionFactory();

        } catch (HibernateException ex) {

            throw new RuntimeException("Exception building SessionFactory: " +

                ex.getMessage(), ex);

        }

    }

 

    public static final ThreadLocal session = new ThreadLocal();

 

    public static Session currentSession() throws HibernateException {

        Session s = (Session) session.get();

 

        //Open a new Session, if this Thread has none yet

        if (s == null) {

            s = sessionFactory.openSession();

            session.set(s);

        }

 

        return s;

    }

 

    public static void closeSession() throws HibernateException {

        Session s = (Session) session.get();

        session.set(null);

 

        if (s != null) {

            s.close();

        }

    }

 

 

}

 

Paras     查询参数

ParasList  查询参数集合

HQuery   封装了查询参数的查询信息类

HibernateDAO 根据传递进来的HQuery进行数据库的查询

有关以上三个类的具体细节,请参考我收藏的文章:Hibernate查询解决方案

 

 

 

2)        Pager 包含了分页信息的类,包括页面总数,记录总数,当前第几页

 

/*

 * @(#)Pager.java    2005-5-3

 *

 * Copyright (c) 2005, Jeffrey Hsu

 */

package com.jeffrey.messagelove;

 

 

/**

 *  Pager holds the page info.

 */

public class Pager {

    private int totalRows = 0; // 记录总数

    private int totalPages = 0; // 总页数

    private int pageSize = 10; // 每页显示数据条数,默认为10条记录

    private int currentPage = 1; // 当前页数

    private boolean hasPrevious = false; // 是否有上一页

    private boolean hasNext = false; // 是否有下一页

 

    public Pager() {

    }

 

    /**

     * Initialize Pager

     * @param totalRows total record rows

     * @param pageSize total record is hold by every page

     */

    public void init(int totalRows, int pageSize) {

        this.totalRows = totalRows;

        this.pageSize = pageSize;

        totalPages = ((totalRows + pageSize) - 1) / pageSize;

        refresh(); // 刷新当前页面信息

    }

 

    /**

     * @return Returns the currentPage.

     */

    public int getCurrentPage() {

        return currentPage;

    }

 

    /**

     * @param currentPage current page

     */

    public void setCurrentPage(int currentPage) {

        this.currentPage = currentPage;

        refresh();

    }

 

    /**

     * @return Returns the pageSize.

     */

    public int getPageSize() {

        return pageSize;

    }

 

    /**

     * @param pageSize The pageSize to set.

     */

    public void setPageSize(int pageSize) {

        this.pageSize = pageSize;

        refresh();

    }

 

    /**

     * @return Returns the totalPages.

     */

    public int getTotalPages() {

        return totalPages;

    }

 

    /**

     * @param totalPages The totalPages to set.

     */

    public void setTotalPages(int totalPages) {

        this.totalPages = totalPages;

        refresh();

    }

 

    /**

     * @return Returns the totalRows.

     */

    public int getTotalRows() {

        return totalRows;

    }

 

    /**

     * @param totalRows The totalRows to set.

     */

    public void setTotalRows(int totalRows) {

        this.totalRows = totalRows;

        refresh();

    }

 

       // 跳到第一页

    public void first() {

        currentPage = 1;

        this.setHasPrevious(false);

        refresh();

    }

 

       // 取得上一页(重新设定当前页面即可)

    public void previous() {

        currentPage--;

        refresh();

    }

 

       // 取得下一页

    public void next() {

        System.out.println("next: totalPages: " + totalPages +

            " currentPage : " + currentPage);

 

        if (currentPage < totalPages) {

            currentPage++;

        }

        refresh();

    }

 

       // 跳到最后一页

    public void last() {

        currentPage = totalPages;

        this.setHasNext(false);

        refresh();

    }

 

    public boolean isHasNext() {

        return hasNext;

    }

 

    /**

     * @param hasNext The hasNext to set.

     */

    public void setHasNext(boolean hasNext) {

        this.hasNext = hasNext;

    }

 

    public boolean isHasPrevious() {

        return hasPrevious;

    }

 

    /**

     * @param hasPrevious The hasPrevious to set.

     */

    public void setHasPrevious(boolean hasPrevious) {

        this.hasPrevious = hasPrevious;

    }

 

       // 刷新当前页面信息

    public void refresh() {

        if (totalPages <= 1) {

            hasPrevious = false;

            hasNext = false;

        } else if (currentPage == 1) {

            hasPrevious = false;

            hasNext = true;

        } else if (currentPage == totalPages) {

            hasPrevious = true;

            hasNext = false;

        } else {

            hasPrevious = true;

            hasNext = true;

        }

    }

}


 

3)        Action:

 

DisplayAllAction   显示数据页面控制器

package com.jeffrey.messagelove;

 

import com.jeffrey.messagelove.*;

import com.jeffrey.messagelove.Pager;

import com.jeffrey.messagelove.hibernate.*;

 

/*

 * @(#)DisplayAction.java    2005-5-2

 *

 * Copyright (c) 2005, Jeffrey Xu

 */

import org.apache.struts.action.*;

 

import java.util.*;

 

import javax.servlet.http.*;

 

 

/**

 *   显示页面控制器

 */

public class DisplayAllAction extends Action {

    private HibernateDAO hibernateDAO = new HibernateDAO();

    private Pager pager = new Pager();

 

    public ActionForward execute(ActionMapping mapping, ActionForm form,

        HttpServletRequest request, HttpServletResponse response)

        throws Exception {

        HttpSession session = request.getSession();

 

        List messageList = null;

        HQuery hquery = new HQuery();

        int totalRows = 0;

        int startRow = 0;

 

        try {

            totalRows = hibernateDAO.getRows("select count(*) from Message");

                     // 初始化页面信息

            pager.init(totalRows, Constants.RECORD_PER_PAGE);

        } catch (Exception ex) {

            ex.printStackTrace();

        }

 

        hquery.setQueryString("From Message order by m_sendDate desc");

 

        String viewPage = (String) request.getParameter("viewPage");

        String action = (String) request.getParameter("action");

             

              // 跳转至相应页面

        if (viewPage != null && !viewPage.equals("")) {

            try {

                pager.setCurrentPage(Integer.parseInt(viewPage));

            } catch (NumberFormatException e) {

                e.printStackTrace();

            }

        }

      

        if (action != null) {

                     // 根据传递进来的参数控制页面的前进后退

            if (action.equalsIgnoreCase("previous")) {

                pager.previous();

            } else if (action.equalsIgnoreCase("next")) {

                pager.next();

            } else if (action.equalsIgnoreCase("first")) {

                pager.first();

            } else if (action.equalsIgnoreCase("last")) {

                pager.last();

            }

        }

        try {

            hquery.setPageStartNo(pager.getCurrentPage());

            messageList = hibernateDAO.find(hquery);

        } catch (Exception ex) {

            ex.printStackTrace();

        }

 

        request.setAttribute("list", messageList);

        session.setAttribute("pager", pager);

 

        return mapping.findForward("display");

    }

}

 

 

 

4)        JSP页面 分页导航代码:

  <%-- 分页导航 --%>

  <table border="0" width="780" class="pageInfo">

    <tr>

      <td width="250">

        <bean:write name="pager" property="totalRows"/><span class="pageInfo">条记录&nbsp;</span>

        <bean:write name="pager" property="currentPage"/>/<bean:write name="pager" property="totalPages"/>

      </td>

      <td align="right" width="60">

        <html:link page="/Displayall.do?viewPage=&action=first">首页</html:link>

      </td>

      <td align="right" width="60"> 

        <logic:equal name="pager" property="hasPrevious" value="true">

          <html:link page="/Displayall.do?viewPage=&action=previous">上一页</html:link>

        </logic:equal>

        <logic:equal name="pager" property="hasPrevious" value="false">

          <span class="invalidLink">上一页</span>

        </logic:equal>

      </td>

      <td align="center" width="4">

        |

      </td>

      <td align="left" width="60">

        <logic:equal name="pager" property="hasNext" value="true" >

          <html:link page="/Displayall.do?viewPage=&action=next">下一页</html:link>

        </logic:equal>

        <logic:equal name="pager" property="hasNext" value="false">

          <span class="invalidLink">下一页</span>

        </logic:equal>

      </td>

      <td width="60">

        <html:link page="/Displayall.do?viewPage=&action=last">末页</html:link>

      </td>

      <td width="160" align="rigth">

       

        <%-- 跳转相应页面,参见下文页面跳转部分 --%>

        <html:form action="/ViewPage.do">

          跳转到

          <html:text property="targetPage" size="3" maxlength="3"/>

          <html:submit value="GO"/>

        </html:form>

      </td>

      <td>

      </td>

    </tr>

  </table>

  <%-- 分页导航结束 --%>

 

5)      页面跳转部分:

Form:

 

ViewPageForm

/*

 * @(#)ViewPageForm.java    2005-5-9

 *

 * Copyright (c) 2005, Jeffrey Xu

 */

package com.jeffrey.messagelove;

 

import org.apache.struts.action.*;

 

public class ViewPageForm extends ActionForm {

       // 欲跳转的目标页面

    private String targetPage;

 

    /**

     * @return Returns the tagetPage.

     */

    public String getTargetPage() {

        return targetPage;

    }

 

    /**

     * @param tagetPage The tagetPage to set.

     */

    public void setTargetPage(String targetPage) {

        this.targetPage = targetPage;

    }

 

}

 

 

 

Action:

根据Form传递进来的目标页面信息跳转之相应的页面

如果输入的数字合法,则跳转至相应的页面,否则跳转至当前页面(在用户看来页面没有变化)

 

/*

 * @(#)ViewPageAction.java    2005-5-9

 *

 * Copyright (c) 2005, Jeffrey Xu

 */

package com.jeffrey.messagelove;

 

import org.apache.struts.action.*;

 

import javax.servlet.http.*;

 

public class ViewPageAction extends Action {

    public ActionForward execute(ActionMapping mapping, ActionForm form,

        HttpServletRequest request, HttpServletResponse response)

        throws Exception {

        String targetPage = ((ViewPageForm) form).getTargetPage();

        HttpSession session = request.getSession();

        Pager pager = (Pager) session.getAttribute("pager");

 

        try {

// 判断是否超出页面范围

            if ((Integer.parseInt(targetPage) > pager.getTotalPages()) ||

                    (Integer.parseInt(targetPage) < 1)) {

                targetPage = String.valueOf(pager.getCurrentPage());

            }

 

                     // 如果输入的不是数字,也就是抛出NumberFormatException异常,

        } catch (NumberFormatException e) {

            e.printStackTrace();

            targetPage = String.valueOf(pager.getCurrentPage());

        }

 

        request.removeAttribute(mapping.getAttribute());

 

        return (new ActionForward("/Displayall.do?viewPage=" + targetPage));

    }

}

 

四、         相关配置

    <form-beans>

            <form-bean name="ViewPageForm" type="com.jeffrey.messagelove.ViewPageForm"/>

    </form-beans>

    <global-forwards>

        <!-- Default forward to "Welcome" action -->

        <!-- Demonstrates using index.jsp to forward -->

        <forward

            name="displayall"

            path="/Displayall.do?viewPage=1"/>

    </global-forwards>

 

 

<!-- =========================================== Action Mapping Definitions -->

 

    <action-mappings>

            <!-- Default "Welcome" action -->

            <!-- Forwards to Welcome.jsp -->

       

       

        <action

            path="/Displayall"

            type="com.jeffrey.messagelove.DisplayAllAction"

            scope="request"

            validate="false"

        >

        </action>

       

        <action

            path="/ViewPage"

            type="com.jeffrey.messagelove.ViewPageAction"

            name="ViewPageForm"

            scope="request"

            validate="false"

        >

            <forward name="viewPage" path="/displayall.do?viewPage="/>

        </action>

       

    </action-mappings>

 

五、         结束:

代码已经全部结束,但是总觉得JSP页面的代码太多,期待有更好的解决办法,比如封装成自定义JSP标签Tag,复用度更高。

还有就是页面跳转部分我想做成下拉列表的方式,根据总页数来动态生成下拉列表,这样更方便一些,并且可以避免用户的错误输入,但我不知该如何根据总页数来动态生成下拉列表,希望哪位朋友能够给出一个解决办法。

 

水平有限,难免有不妥的地方,如果您有好的意见或建议请回复或与我联系,在下感激不尽!

jeffreyxu@gmail.com

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值