it167.com  设为主页
 收藏本站
 
  资讯:业界动态 | 软件动态 | 人物专栏 | 安全资讯 | 网络生活 | 电子商务 | 小游戏 | 视频 | 美女图片 | 音乐
  网络编程 | 网站运营 | 网页制作 | 图形图象 | 操作系统 | 媒体动画 | 软件教学 | 网络应用 | 邮件系统 | 网络安全 | 认证考试
asp | .net | php | jsp | Sql | java | Dreamweaver | FrontPages | Javascript | css | Coreldraw | photoshop | Flash | Coreldraw
当前位置: > 主页>网络编程>Jsp>Jsp开发技巧>高效简洁的Struts分页技巧
最新新闻

·机会与整合 边缘化互联
·TOM-Skype新增三大本地
·雅虎抢闸邮箱竞赛 网易
·新浪抢攻北京奥运
·洞悉网络口碑的掘金机会
·拆解网络病毒黑金交易
·木马下载器近期出现新变
·《互联网周刊》第17期文
·Web2.0是否催生自吹自擂
·三张宝宝裸照招来MSN封
热门新闻
·J2EE架构初学者的6个最
·jsp彩色汉字验证码教程
·jsp彩色汉字验证码教程
·Eclipse插件开发之定制
·一个开发人员眼中的JSP
·一个开发人员眼中的JSP
·JavaBean在JSP中的应用
·在JSP中访问数据库方法
·JSP中文乱码问题解决方
·JSP标签库介绍
推荐新闻
 
 

高效简洁的Struts分页技巧  

作者:   来源:   点击:   日期:2007-11-29

【摘 要】在网上看了几个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 "";
   }
   }
   }
  
   这部分代码的实现相当简洁,但已经足够完成所需了。



文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【论坛讨论

   相关文章:
·jsp彩色汉字验证码教程 ·J2EE架构初学者的6个最佳实践
·jsp彩色汉字验证码教程 ·Eclipse插件开发之定制向导学习
·一个开发人员眼中的JSP技术(下) ·一个开发人员眼中的JSP技术(上)

   文章评论:(0条)
  
 请留名: 匿名评论   点击查看所有评论 网管论坛
 

  责任编辑:it167  声明:刊登此文章是为了传递更多信息,文章内容仅供参考,转载请注明出处。