一个高效简洁的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 CertificateActionextends 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 ffset = 0;  //翻页时的起始记录所在游标int length = PAGE_LENGTH;String pageOffset = request.getParameter("pager.offset");if (pageOffset == null || pageOffset.equals("")) {ffset = 0;} else {ffset = 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" %>

& && " class="a02"> Previous " class="a02"> Next

"/>

6、对应的配置文件struts-config.xml。

java代码:

代码:

……

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 = ""+HEADER+": ";if (offset > 0) {header += "&[<< Prev]/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;iif (i == offset) {header += ""+(i/size+1)+"/n";} else {header += "&"+(i/size+1)+"/n";}}if(offset < length - size) {header += "&[Next >>]/n";}header += "";return header;} else {return "";}}}

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

三亚呀——赴一个蓝天碧海。只是微笑地固执自己的坚持,

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

相关文章:

你感兴趣的文章:

标签云: