分享
 
 
 

一个高效简洁的Struts分页方法

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

在网上看了几个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" "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、最后当然是最重要的分页代码了: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 "";

}

}

}

这部分代码的实现相当简洁,但已经足够完成所需了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有