posts - 61,  comments - 2033,  trackbacks - 0

              在網(wǎng)上看了幾個(gè)Structs分頁(yè),感覺(jué)不是很完善,于是根據(jù)自己的經(jīng)驗(yàn),寫了一個(gè)相對(duì)高效簡(jiǎn)潔的分頁(yè)方法。由于本人水平有限,如果大家有什么更好的想法,歡迎不吝賜教。

          一、 開(kāi)發(fā)環(huán)境
          我的開(kāi)發(fā)環(huán)境是:JBuilder x + Weblogic 8.1 + Oracle 9i + Windows 2003 ,如果朋友們的開(kāi)發(fā)環(huán)境不一樣亦無(wú)妨。

          二、開(kāi)發(fā)思路
          既然講的是Struts,那自然離不了MVC,分頁(yè)顯示也是如此。
          1、 建立數(shù)據(jù)庫(kù)和對(duì)應(yīng)的表,本例的表是TCertificate。
          2、 建立適當(dāng)?shù)哪P徒M件,對(duì)應(yīng)你要查詢數(shù)據(jù)庫(kù)中的表。這部分由DAO數(shù)據(jù)訪問(wèn)層來(lái)實(shí)現(xiàn),如果有的朋友對(duì)DAO不熟悉可以查詢一下相關(guān)資料。本例由CertificateDAO.java來(lái)實(shí)現(xiàn)。
          3 、建立分頁(yè)所需要的模型組件,由javaBean來(lái)充當(dāng),并與CertificateDAO實(shí)現(xiàn)分離。網(wǎng)上介紹的很多方法,都存在著數(shù)據(jù)與分頁(yè)組件藕合的現(xiàn)象,這也是本方法與其它分頁(yè)方法的主要不同之處。

          4、建立控制器組件,這部分由Struts 中的Action來(lái)實(shí)現(xiàn)。主要負(fù)責(zé)將實(shí)例化CertificateDAO,只取要顯示的數(shù)據(jù)記錄,存入ArrayList對(duì)象然后返回,并放到request中。而分頁(yè)部分則根據(jù)分頁(yè)條件,單獨(dú)進(jìn)行構(gòu)造,避免了與DAO混在一起的情況發(fā)生。網(wǎng)上其它介紹的一些分頁(yè)方法中,基本上都是一次性讀出所有查詢的數(shù)據(jù),然后再由分頁(yè)相關(guān)組件進(jìn)行構(gòu)造。這樣,如果數(shù)據(jù)量大的話,很容易形成瓶頸。在本例中由于不是一次性地讀出查詢的所有數(shù)據(jù),而只是讀出一個(gè)頁(yè)面要顯示的數(shù)據(jù)記錄,這就節(jié)省了很多不必要的數(shù)據(jù)傳輸,提高了效率。本例中為CertificateAction.java。

          5、建立視圖組件,這部分由jsp來(lái)充當(dāng),為了不出現(xiàn)java 代碼,我們使用Struts提供的標(biāo)簽庫(kù),主要負(fù)責(zé)從request中取出剛剛放入的對(duì)象,通過(guò)反復(fù)調(diào)用CertificateAction以及action參數(shù),而實(shí)現(xiàn)分頁(yè)顯示。本例中為listcertificate.jsp。
          6、 建立并配置struts-config.xml。

          三、實(shí)例代碼
          確定好上面的開(kāi)發(fā)思路后,代碼的實(shí)現(xiàn)就有單可循了。
          1、建數(shù)據(jù)庫(kù)和相應(yīng)的表。
          2、數(shù)據(jù)邏輯層的相關(guān)代碼。
          1)、通用的DAO類:CommonDAO.java
          這是一個(gè)很多DAO都要繼承到的通用DAO類,是我根據(jù)實(shí)踐總結(jié)出來(lái)的,為了減少篇幅,這里只顯示和本例相關(guān)的代碼。


          java代碼:

          package com.xindeco.business ;
          import java.io.*;
          import java.sql.*;
          import java.util.*;
          import javax.sql.*;
          import java.lang.IllegalAccessException;
          import java.lang.reflect.InvocationTargetException;
          import org.apache.commons.beanutils.BeanUtils;
          public class DAO
          {
            protected DataSource ds;
          /**
            * 說(shuō)明:取得當(dāng)前查詢的總記錄數(shù)
            */
          public int getRows ()
          {
            return this.count;
          }
            public void rsHandler (ResultSet rs, int offset, int limit)
            {
             try
             {
              count = 0;
              rs.absolute ( -1) ;
              count = rs.getRow () ;
              if (offset <= 0)
              {
               rs.beforeFirst () ;
              }
              else
              {
               rs.absolute (offset) ;
              }
             }
             catch (Exception e)
             {
              e.printStackTrace () ;
             }
            }
            public DAO(DataSource ds) {
                    this.ds = ds;
            }

            public void setDataSource(DataSource ds) {
              this.ds = ds;
            }

            protected void close(ResultSet rs) {
              if (rs != null) {
                      try {
                              rs.close();
                      } catch (SQLException e) {
                      }
                      rs = null;
              }
            }

            protected void close(PreparedStatement pstmt) {
              if (pstmt != null) {
                      try {
                              pstmt.close();
                      } catch (SQLException e) {
                      }
                      pstmt = null;
              }
            }
            protected void close(Connection conn) {
              if (conn != null) {
                      try {
                              conn.close();
                      } catch (SQLException e) {
                              e.printStackTrace();
                      }
                      conn = null;
              }
            }

            protected void rollback(Connection conn) {
              if (conn != null) {
                      try {
                              conn.rollback();
                      } catch (SQLException e) {
                              e.printStackTrace();
                      }
                      conn = null;
              }
            }
          }


          這個(gè)類主要是通過(guò)子類傳進(jìn)來(lái)的先進(jìn)結(jié)果集,取得查詢的記錄總數(shù),并對(duì)數(shù)據(jù)庫(kù)連接進(jìn)行簡(jiǎn)單的管理。
          2)、對(duì)數(shù)據(jù)庫(kù)進(jìn)行訪問(wèn):CertificateDAO.java


          java代碼:

          package com.xindeco.business;

          import java.io.*;
          import java.sql.*;
          import java.util.*;
          import javax.sql.*;

          import com.xindeco.common.dbconn.DbConn;

          public class CertificateDAO extends DAO
          {

            public NationDAO(DataSource ds) {
              super(ds);
            }

          public List findCertificateList(int offset,int limit) throws SQLException
                  {
                  int countRows = 0 ;
                  ArrayList list = null ;
              Connection conn = null;
              PreparedStatement pstmt = null;
          ResultSet rs = null;
          try
                  {
                       conn = ds.getConnection();
                          String sql =
                                          "SELECT certificateID, certificateCode,certificateName,photoURL,"
                                          + "description,graduateID FROM TCertificate " ;
                pstmt = conn.prepareStatement(sql);
                rs = pstmt.executeQuery();
                                  /*對(duì)游標(biāo)進(jìn)行處理,rsHandler 方法在父類DAO中*/
                                  this.rsHandler(rs,offset,limit);
                                  if (rs != null && rs.next ())
                                  {
                                          list = new ArrayList () ;
                                          do
                                          {
                                                  countRows++ ;
                                                  list.add (rs2VO (rs)) ;
                                          }
                                          while ( (countRows++ < limit) && rs.next ()) ;
                                  }
                close(rs);
                close(pstmt);
                    } catch (SQLException e) {
                close(rs);
                close(pstmt);
                rollback(conn);
                          e.printStackTrace();
                            }
          finally {
                      close(conn);
              }
                  return list ;
                  }

                  private CertificateVO rs2VO (ResultSet rs)
                  {
                          try
                          {
                                  CertificateVO certificateVO = new CertificateVO () ;
                                  certificateVO.setCertificateID (rs.getInt ("certificateID")) ;
                                  certificateVO.setCertificateCode (rs.getString ("certificateCode")) ;
                                  certificateVO.setCertificateName (rs.getString ("certificateName")) ;
                                  certificateVO.setPhotoURL (rs.getString ("photoURL")) ;
                                  certificateVO.setDescription (rs.getString ("description")) ;
                                  certificateVO.setGraduateID (rs.getInt ("graduateID")) ;
                                  return certificateVO ;
                          }
                          catch (Exception ex)
                          {
                                  ex.printStackTrace () ;
                                  return null ;
                          }
                  }
          }

          findCertificateList(int offset,int limit)是查得所有要顯示的數(shù)據(jù),并放入ArrayList中。看過(guò)網(wǎng)上有些例子,把數(shù)據(jù)記錄放入ArrayList的動(dòng)作過(guò)程直接在while循環(huán)體里完成,如果字段多的話,會(huì)造成方法過(guò)于寵大,又不美觀。 這里,數(shù)據(jù)記錄放入ArrayList的動(dòng)作過(guò)程由rs2VO方法完成,就比較整潔了。另外,if (rs != null && rs.next ()) 配合while ( (countRows++ < limit) && rs.next ()) 是為了程序的健壯性考慮的,稍分析一下不難得出結(jié)論。

          3、建立控制器組件:CertificateAction.java


          java代碼:

          package com.xindeco.presentation;

          import javax.sql.* ;
          import java.util.* ;

          import javax.servlet.http.* ;
          import javax.servlet.* ;

          import org.apache.struts.action.* ;
          import org.apache.struts.util.* ;

          import com.xindeco.common.Pager;
          import com.xindeco.business.graduatedata.CertificateDAO ;

          public class CertificateAction
                  extends Action
          {
                  private static final int PAGE_LENGTH = 5 ; //每頁(yè)顯示5條記錄
                  public ActionForward execute (ActionMapping mapping, ActionForm form,
                                                                            HttpServletRequest request,
                                                                            HttpServletResponse response)
                  {
                          ActionForward myforward = null ;
                          String myaction = mapping.getParameter () ;

                          if (isCancelled (request))
                          {
                                  return mapping.findForward ("failure") ;
                          }
                          if ("".equalsIgnoreCase (myaction))
                          {
                                  myforward = mapping.findForward ("failure") ;
                          }
                          else if        ("LIST".equalsIgnoreCase (myaction))
                          {
                                  myforward = performList (mapping, form, request, response) ;
                          }
                          else
                          {
                                  myforward = mapping.findForward ("failure") ;
                          }
                          return myforward ;
                  }

                  private ActionForward performList (ActionMapping mapping,
                                                                                     ActionForm actionForm,
                                                                                     HttpServletRequest request,
                                                                                     HttpServletResponse response)
                  {
                               try
                          {
                  DataSource ds = (DataSource) servlet.getServletContext().getAttribute(Action.DATA_SOURCE_KEY);

                          CertificateDAO   certificateDAO  = new CertificateDAO  (ds) ;

                                  int offset = 0;   //翻頁(yè)時(shí)的起始記錄所在游標(biāo)
                                  int length = PAGE_LENGTH;  
                                  String pageOffset = request.getParameter("pager.offset");
                          if (pageOffset == null || pageOffset.equals("")) {
                  offset = 0;
                } else {
                  offset = Integer.parseInt(pageOffset);
                }
                                  List certificateList = certificateDAO .findCertificateList (offset,length) ;
                                  int size = certificateDAO.getRows(); //  取得總記錄數(shù)
                                  String url = request.getContextPath()+"/"+mapping.getPath()+".do";
                                  String pagerHeader = Pager.generate(offset, size, length, url); //分頁(yè)處理

                                  request.setAttribute ("pager", pagerHeader) ;
                                  request.setAttribute ("list", certificateList) ;
                          }
                          catch (Exception e)
                          {
                                  e.printStackTrace();
                                  return mapping.findForward ("error") ;
                          }
                          return mapping.findForward ("success") ;
                  }
          }


          CertificateAction.java主要是把數(shù)據(jù)從DAO中取出,并放入一個(gè)ArrayList 中,然后通過(guò)配置文件再軟件View的JSP頁(yè)。

          5、建立視圖listcertificate.jsp文件。

          java代碼:

          <%@ page contentType="text/html; charset=GBK" %>
          <%@ taglib uri="/WEB-INF/struts-template.tld" prefix="template" %>
          <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
          <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
          <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

          <table bgcolor="#666666" cellpadding="1" cellspacing="0" border="0" width="500">
          <tr>
          <td>
          <table cellpadding="0" cellspacing="0" border="0" width="500">
          <tr>
          <td bgcolor="#fecc51">&</td>
          </tr>
          </table>
          </td>
          </tr>
          <tr>
          <td>
          <table cellpadding="0" cellspacing="0" border="0" width="500">
            <tr>
          <td bgcolor="#d6e0ed">
              &&<bean:message key="label.list4certificate"/>
            </td>
          </tr>
          <tr bgcolor="#FFFFFF">
          <td width="5%"></td><td width="19%"></td><td width="76%"></td>
          </tr>
              <tr>
          <td>
          <table bgcolor="#f2f2f2" width="500" cellspacing="0" border="0">
                <tr bgcolor="#bacce1">
                  <td><b><bean:message key="Certificate.select"/> </b></td>
                  <td><b><bean:message key="Certificate.certificateID"/> </b></td>
                  <td><b><bean:message key="Certificate.certificateCode"/></b></td>
                  <td><b><bean:message key="Certificate.certificateName"/></b></td>
                  <td><b><bean:message key="Certificate.view"/></b></td>
              ?/tr>

          <bean:write name="pager" property="description"/>
            <logic:equal name="pager" property="hasPrevious" value="true">
                        <a href="/graduatedata/list.do?viewPage=<bean:write name="pager" property="previousPage"/>" class="a02">
                     Previous
                  </a>
            </logic:equal>
            <logic:equal name="pager" property="hasNext" value="true">
              ?a href="/graduatedata/list.do?viewPage=<bean:write name="pager" property="nextPage"/>" class="a02">
               Next
              ?/a>
            </logic:equal>

          <logic:notEmpty name="list" scope="request">
          <logic:iterate id="certificate" name="list" type="com.xindeco.business.graduatedata.CertificateVO"scope="request">
          <tr bgcolor="#FFFFFF">
              ?td><html:text property="name" value="<bean:write name="certificate" property="certificateID" scope="page"/>"/>
                          </td>
              ?td> <bean:write name="certificate" property="certificateID" scope="page"/></td>
              ?td> <bean:write name="certificate" property="certificateCode" scope="page"/></td>
              ?td> <bean:write name="certificate" property="certificateName" scope="page"/></td>
              ?td> <bean:write name="certificate" property="photoURL" scope="page"/></td>
          </tr>
          </logic:iterate>
          </logic:notEmpty>
          </table>
          </td>
          </tr>
          </table>
          </td>
          </tr>
          </table>

          6、對(duì)應(yīng)的配置文件struts-config.xml。

          java代碼:

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
          <struts-config>
            <form-beans>
              <form-bean name="certificateForm" type="com.xindeco.presentation.graduatedata.CertificateForm" />
            </form-beans>
            <global-forwards>
              <forward name="error" path="/error/error.jsp" />
            </global-forwards>
            <action-mappings>
                <action name="certificateForm" parameter="LIST" path="/graduatedata/list" scope="request" type="com.xindeco.presentation.graduatedata.CertificateAction" validate="true">
                <forward name="success" path="/graduatedata/listcertificate.jsp" />
              </action>
            </action-mappings>
          ……
          </struts-config>

          7、最后當(dāng)然是最重要的分頁(yè)代碼了:Pager.java

          java代碼:

          package com.xindeco.common;

          import java.util.* ;
          public class Pager {
            private static int MAX_PAGE_INDEX = 10; //頁(yè)腳顯示多少頁(yè)
            private static String HEADER = "Result page";
            
            public static String generate(int offset, int length, int size, String url) {
                  if (length > size) {
                    String pref;
                    if (url.indexOf("?") > -1) {
                          pref = "&";
                    } else {
                          pref = "?";
                    }
                    String header = "<font face='Helvetica' size='-1'>"+HEADER+": ";
                    if (offset > 0) {
                          header += "&<a href=\""+url+pref+"pager.offset="+(offset-size)+"\">[<< Prev]</a>\n";
                    }
                    int start;
                    int radius = MAX_PAGE_INDEX/2*size;
                    if (offset < radius) {
                          start = 0;
                    } else if(offset < length-radius) {
                          start = offset - radius;
                    } else {
                          start = (length/size-MAX_PAGE_INDEX)*size;
                    }
                    for(int i=start;i<length && i < start + MAX_PAGE_INDEX*size;i+=size) {
                          if (i == offset) {
                            header += "<b>"+(i/size+1)+"</b>\n";
                          } else {
                            header += "&<a href=\""+url+pref+"pager.offset="+i+"\">"+(i/size+1)+"</a>\n";
                          }
                    }
                    if(offset < length - size) {
                          header += "&<a href=\""+url+pref+"pager.offset="+((int)offset+(int)size)+"\">[Next >>]</a>\n";
                    }
                    header += "</font>";
                    return header;
                  } else {
                    return "";
                  }
            }
          }

          這部分代碼的實(shí)現(xiàn)相當(dāng)簡(jiǎn)潔,但已經(jīng)足夠完成所需了。

          posted on 2005-11-09 18:03 魚上游 閱讀(1361) 評(píng)論(0)  編輯  收藏 所屬分類: 爪哇世界探險(xiǎn)
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(82)

          隨筆分類(59)

          文章分類(21)

          相冊(cè)

          收藏夾(40)

          GoodSites

          搜索

          •  

          積分與排名

          • 積分 - 1267734
          • 排名 - 22

          最新評(píng)論

          閱讀排行榜

          主站蜘蛛池模板: 西宁市| 洛南县| 富阳市| 谢通门县| 固镇县| 蚌埠市| 丘北县| 清苑县| 新建县| 呼图壁县| 容城县| 香港| 蒙山县| 同心县| 城市| 巴马| 托克逊县| 乌苏市| 武功县| 九龙坡区| 九江县| 江源县| 景谷| 叙永县| 沙洋县| 滕州市| 玛沁县| 永丰县| 玉田县| 镇平县| 南宫市| 惠安县| 云安县| 曲阳县| 寻乌县| 洛阳市| 易门县| 家居| 宽甸| 曲阳县| 屯门区|