一個(gè)高效簡(jiǎn)潔的Struts分頁(yè)方法
2024-07-21 02:15:04
供稿:網(wǎng)友
在網(wǎng)上看了幾個(gè)structs分頁(yè),感覺不是很完善,于是根據(jù)自己的經(jīng)驗(yàn),寫了一個(gè)相對(duì)高效簡(jiǎn)潔的分頁(yè)方法。由于本人水平有限,如果大家有什么更好的想法,歡迎不吝賜教。
一、 開發(fā)環(huán)境
我的開發(fā)環(huán)境是:jbuilder x + weblogic 8.1 + oracle 9i + windows 2003 ,如果朋友們的開發(fā)環(huán)境不一樣亦無妨。
二、開發(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ù)訪問層來實(shí)現(xiàn),如果有的朋友對(duì)dao不熟悉可以查詢一下相關(guān)資料。本例由certificatedao.java來實(shí)現(xiàn)。
3 、建立分頁(yè)所需要的模型組件,由javabean來充當(dāng),并與certificatedao實(shí)現(xiàn)分離。網(wǎng)上介紹的很多方法,都存在著數(shù)據(jù)與分頁(yè)組件藕合的現(xiàn)象,這也是本方法與其它分頁(yè)方法的主要不同之處。
4、建立控制器組件,這部分由struts 中的action來實(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來充當(dāng),為了不出現(xiàn)java 代碼,我們使用struts提供的標(biāo)簽庫(kù),主要負(fù)責(zé)從request中取出剛剛放入的對(duì)象,通過反復(fù)調(diào)用certificateaction以及action參數(shù),而實(shí)現(xiàn)分頁(yè)顯示。本例中為listcertificate.jsp。
6、 建立并配置struts-config.xml。
三、實(shí)例代碼
確定好上面的開發(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é)出來的,為了減少篇幅,這里只顯示和本例相關(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ù)庫(kù)連接進(jìn)行簡(jiǎn)單的管理。
2)、對(duì)數(shù)據(jù)庫(kù)進(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 ; //每頁(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 中,然后通過配置文件再軟件view的jsp頁(yè)。
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" "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)足夠完成所需了。