| | 在網(wǎng)上看了幾個(gè)Structs分頁,感覺不是很完善,于是根據(jù)自己的經(jīng)驗(yàn),寫了一個(gè)相對(duì)高效簡潔的分頁方法。由于本人水平有限,如果大家有什么更好的想法,歡迎不吝賜教。
一、 開發(fā)環(huán)境 我的開發(fā)環(huán)境是:JBuilder x + Weblogic 8.1 + Oracle 9i + Windows 2003 ,如果朋友們的開發(fā)環(huán)境不一樣亦無妨。
二、開發(fā)思路 既然講的是Struts,那自然離不了MVC,分頁顯示也是如此。 1、 建立數(shù)據(jù)庫和對(duì)應(yīng)的表,本例的表是TCertificate。 2、 建立適當(dāng)?shù)哪P徒M件,對(duì)應(yīng)你要查詢數(shù)據(jù)庫中的表。這部分由DAO數(shù)據(jù)訪問層來實(shí)現(xiàn),如果有的朋友對(duì)DAO不熟悉可以查詢一下相關(guān)資料。本例由CertificateDAO.java來實(shí)現(xiàn)。 3 、建立分頁所需要的模型組件,由javaBean來充當(dāng),并與CertificateDAO實(shí)現(xiàn)分離。網(wǎng)上介紹的很多方法,都存在著數(shù)據(jù)與分頁組件藕合的現(xiàn)象,這也是本方法與其它分頁方法的主要不同之處。
4、建立控制器組件,這部分由Struts 中的Action來實(shí)現(xiàn)。主要負(fù)責(zé)將實(shí)例化CertificateDAO,只取要顯示的數(shù)據(jù)記錄,存入ArrayList對(duì)象然后返回,并放到request中。而分頁部分則根據(jù)分頁條件,單獨(dú)進(jìn)行構(gòu)造,避免了與DAO混在一起的情況發(fā)生。網(wǎng)上其它介紹的一些分頁方法中,基本上都是一次性讀出所有查詢的數(shù)據(jù),然后再由分頁相關(guān)組件進(jìn)行構(gòu)造。這樣,如果數(shù)據(jù)量大的話,很容易形成瓶頸。在本例中由于不是一次性地讀出查詢的所有數(shù)據(jù),而只是讀出一個(gè)頁面要顯示的數(shù)據(jù)記錄,這就節(jié)省了很多不必要的數(shù)據(jù)傳輸,提高了效率。本例中為CertificateAction.java。
5、建立視圖組件,這部分由jsp來充當(dāng),為了不出現(xiàn)java 代碼,我們使用Struts提供的標(biāo)簽庫,主要負(fù)責(zé)從request中取出剛剛放入的對(duì)象,通過反復(fù)調(diào)用CertificateAction以及action參數(shù),而實(shí)現(xiàn)分頁顯示。本例中為listcertificate.jsp。 6、 建立并配置struts-config.xml。
三、實(shí)例代碼 確定好上面的開發(fā)思路后,代碼的實(shí)現(xiàn)就有單可循了。 1、建數(shù)據(jù)庫和相應(yīng)的表。 2、數(shù)據(jù)邏輯層的相關(guān)代碼。 1)、通用的DAO類:CommonDAO.java 這是一個(gè)很多DAO都要繼承到的通用DAO類,是我根據(jù)實(shí)踐總結(jié)出來的,為了減少篇幅,這里只顯示和本例相關(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; /** * 說明:取得當(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è)類主要是通過子類傳進(jìn)來的先進(jìn)結(jié)果集,取得查詢的記錄總數(shù),并對(duì)數(shù)據(jù)庫連接進(jìn)行簡單的管理。 2)、對(duì)數(shù)據(jù)庫進(jì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中??催^網(wǎng)上有些例子,把數(shù)據(jù)記錄放入ArrayList的動(dòng)作過程直接在while循環(huán)體里完成,如果字段多的話,會(huì)造成方法過于寵大,又不美觀。 這里,數(shù)據(jù)記錄放入ArrayList的動(dòng)作過程由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 ; //每頁顯示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; //翻頁時(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); //分頁處理
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 中,然后通過配置文件再軟件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、對(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" "‘ target=_blank>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)然是最重要的分頁代碼了: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 ""; } } }
|
|
|
|
|
|
|
|
|
|