posts - 4,comments - 30,trackbacks - 0

一、 开发环境
  
  我的开发环境是: 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" "<a href="http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">" target="_blank">http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"></a>  

   <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 "";   

    }   

  }   

}  


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

posted on 2007-08-06 14:13 蛮哥♂枫 阅读(2763) 评论(1)  编辑  收藏 所属分类: Java

FeedBack:
# re: java分页组件 (转)
2008-11-05 16:50 | 史蒂芬
代码过于冗余了  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: