龍行天下

            政 博
          隨筆 - 23, 文章 - 0, 評論 - 12, 引用 - 0
          數據加載中……

          一個高效簡潔的Struts分頁方法

          在網上看了幾個Structs分頁,感覺不是很完善,于是根據自己的經驗,寫了一個相對高效簡潔的分頁方法。由于本人水平有限,如果大家有什么更好的想法,歡迎不吝賜教。
            
            一、 開發環境
            
            我的開發環境是:JBuilder x + Weblogic 8.1 + Oracle 9i + Windows 2003 ,如果朋友們的開發環境不一樣亦無妨。
            
            二、開發思路
            
            既然講的是Struts,那自然離不了MVC,分頁顯示也是如此。
            
            1、 建立數據庫和對應的表,本例的表是TCertificate。
            
            2、 建立適當的模型組件,對應你要查詢數據庫中的表。這部分由DAO數據訪問層來實現,如果有的朋友對DAO不熟悉可以查詢一下相關資料。本例由CertificateDAO.java來實現。
            
            3 、建立分頁所需要的模型組件,由javaBean來充當,并與CertificateDAO實現分離。網上介紹的很多方法,都存在著數據與分頁組件藕合的現象,這也是本方法與其它分頁方法的主要不同之處。
            
            4、建立控制器組件,這部分由Struts 中的Action來實現。主要負責將實例化CertificateDAO,只取要顯示的數據記錄,存入ArrayList對象然后返回,并放到 request中。而分頁部分則根據分頁條件,單獨進行構造,避免了與DAO混在一起的情況發生。網上其它介紹的一些分頁方法中,基本上都是一次性讀出所有查詢的數據,然后再由分頁相關組件進行構造。這樣,如果數據量大的話,很容易形成瓶頸。在本例中由于不是一次性地讀出查詢的所有數據,而只是讀出一個頁面要顯示的數據記錄,這就節省了很多不必要的數據傳輸,提高了效率。本例中為CertificateAction.java。
            
             5、建立視圖組件,這部分由jsp來充當,為了不出現java 代碼,我們使用Struts提供的標簽庫,主要負責從request中取出剛剛放入的對象,通過反復調用CertificateAction以及 action參數,而實現分頁顯示。本例中為listcertificate.jsp。
            
            6、 建立并配置struts-config.xml。
            
            三、實例代碼
            
            確定好上面的開發思路后,代碼的實現就有單可循了。
            
            1、建數據庫和相應的表。
            
            2、數據邏輯層的相關代碼。
            
            1)、通用的DAO類:CommonDAO.java
            
            這是一個很多DAO都要繼承到的通用DAO類,是我根據實踐總結出來的,為了減少篇幅,這里只顯示和本例相關的代碼。
            
            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;
            /**
            * 說明:取得當前查詢的總記錄數
            */
            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;
            }
            }
            }
            
            這個類主要是通過子類傳進來的先進結果集,取得查詢的記錄總數,并對數據庫連接進行簡單的管理。
            
            2)、對數據庫進行訪問: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();
            /*對游標進行處理,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)是查得所有要顯示的數據,并放入ArrayList中。看過網上有些例子,把數據記錄放入ArrayList的動作過程直接在while循環體里完成,如果字段多的話,會造成方法過于寵大,又不美觀。這里,數據記錄放入ArrayList的動作過程由rs2VO方法完成,就比較整潔了。另外,if (rs != null && rs.next ()) 配合while ( (countRows++ < limit) && rs.next ()) 是為了程序的健壯性考慮的,稍分析一下不難得出結論。
            
            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 ; //每頁顯示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;  //翻頁時的起始記錄所在游標
            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(); // 取得總記錄數
            String url = request.getContextPath()+"/"+mapping.getPath()+".do";
            String pagerHeader = Pager.generate(offset, size, length, url); //分頁處理
            
            request.setAttribute ("pager", pagerHeader) ;
            request.setAttribute ("list", certificateList) ;
            }
            catch (Exception e)
            {
            e.printStackTrace();
            return mapping.findForward ("error") ;
            }
            return mapping.findForward ("success") ;
            }
            }
            
            CertificateAction.java主要是把數據從DAO中取出,并放入一個ArrayList 中,然后通過配置文件再軟件View的JSP頁。
            
            5、建立視圖listcertificate.jsp文件。
            
            jsp代碼:
            
            代碼:
            --------------------------------------------------------------------------------
            
            <%@ 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、對應的配置文件struts-config.xml。
            
            java代碼:
            
            代碼:
            --------------------------------------------------------------------------------
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "  <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、最后當然是最重要的分頁代碼了:Pager.java
            
            java代碼:
            
            代碼:
            --------------------------------------------------------------------------------
            package com.xindeco.common;
            
            import java.util.* ;
            public class Pager {
            private static int MAX_PAGE_INDEX = 10; //頁腳顯示多少頁
            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 "";
            }
            }
            }
            
            這部分代碼的實現相當簡潔,但已經足夠完成所需了。

          posted on 2006-05-03 20:04 feingto 閱讀(318) 評論(0)  編輯  收藏 所屬分類: Java Web

          主站蜘蛛池模板: 明溪县| 湖北省| 南阳市| 九江县| 宁晋县| 安陆市| 金寨县| 名山县| 济源市| 义马市| 马山县| 板桥市| 新安县| 富阳市| 凤台县| 上林县| 泰顺县| 文安县| 宿迁市| 吴川市| 临湘市| 宝清县| 南和县| 井陉县| 石屏县| 丁青县| 遂平县| 即墨市| 容城县| 永州市| 东光县| 古丈县| 佛坪县| 东乌珠穆沁旗| 革吉县| 肇州县| 嫩江县| 枣庄市| 安阳县| 昆明市| 巴南区|