马尔代夫
学会真心付出
posts - 0,comments - 0,trackbacks - 0

和绝大多数分页一样,本例也是把所有数据查询出来,然后通过 rsHandler (rs,offset,limit)来取出当前页所该显示的数据,这样做非常消耗系统资源,如果数据库中存在几十万数据,估计服务器成拖拉机了

  1.   conn = ds.getConnection();
  2.   String sql =
  3.   "SELECT certificateID, certificateCode,certificateName,photoURL,"
  4.   + "description,graduateID FROM TCertificate " ;
  5.   pstmt = conn.prepareStatement(sql);
  6.   rs = pstmt.executeQuery();
  7.   /*对游标进行处理,rsHandler 方法在父类DAO中*/
  8.   this.rsHandler(rs,offset,limit);

---------------------------------------------------------------------------------------------------

2006/8/29 2:00 

随便看了下,就看最后的生成 页码 的部分,里边包含了太多的应该放在Html里边的东西,显然这样是不对的。目前自己的想法是生成的页码存放在一个List中,然后返回给叶面,页面再通过logic:iterate 生成相应的html,这样代码应该可以完全脱离页面了。

 以下为转载内容

在网上看了几个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类,是我根据实践总结出来的,为了减少篇幅,这里只显示和本例相关的代码。

				
JavaZoo.com © 2006. Code Language:java.
  1. package com.xindeco.business ;
  2.   import java.io.*;
  3.   import java.sql.*;
  4.   import java.util.*;
  5.   import javax.sql.*;
  6.   import java.lang.IllegalAccessException;
  7.   import java.lang.reflect.InvocationTargetException;
  8.   import org.apache.commons.beanutils.BeanUtils;
  9.   publicclass DAO
  10.   {
  11.   protected DataSource ds;
  12.   /**
  13.   * 说明:取得当前查询的总记录数
  14.   */
  15.   publicint getRows ()
  16.   {
  17.   returnthis.count;
  18.   }
  19.   publicvoid rsHandler (ResultSet rs, int offset, int limit)
  20.   {
  21.   try
  22.   {
  23.   count = 0;
  24.   rs.absolute(-1) ;
  25.   count = rs.getRow() ;
  26.   if(offset <= 0)
  27.   {
  28.   rs.beforeFirst() ;
  29.   }
  30.   else
  31.   {
  32.   rs.absolute(offset) ;
  33.   }
  34.   }
  35.   catch(Exception e)
  36.   {
  37.   e.printStackTrace() ;
  38.   }
  39.   }
  40.   public DAO(DataSource ds){
  41.   this.ds = ds;
  42.   }
  43.   
  44.   publicvoid setDataSource(DataSource ds){
  45.   this.ds = ds;
  46.   }
  47.   
  48.   protectedvoid close(ResultSet rs){
  49.   if(rs != null){
  50.   try{
  51.   rs.close();
  52.   }catch(SQLException e){
  53.   }
  54.   rs = null;
  55.   }
  56.   }
  57.   
  58.   protectedvoid close(PreparedStatement pstmt){
  59.   if(pstmt != null){
  60.   try{
  61.   pstmt.close();
  62.   }catch(SQLException e){
  63.   }
  64.   pstmt = null;
  65.   }
  66.   }
  67.   protectedvoid close(Connection conn){
  68.   if(conn != null){
  69.   try{
  70.   conn.close();
  71.   }catch(SQLException e){
  72.   e.printStackTrace();
  73.   }
  74.   conn = null;
  75.   }
  76.   }
  77.   
  78.   protectedvoid rollback(Connection conn){
  79.   if(conn != null){
  80.   try{
  81.   conn.rollback();
  82.   }catch(SQLException e){
  83.   e.printStackTrace();
  84.   }
  85.   conn = null;
  86.   }
  87.   }
  88.   }
  89.  
  90.  
Parsed in 0.186 seconds, using GeSHi 1.0.7.12

  这个类主要是通过子类传进来的先进结果集,取得查询的记录总数,并对数据库连接进行简单的管理。
  
  2)、对数据库进行访问:CertificateDAO.java

								
JavaZoo.com © 2006. Code Language:java.
  1. package com.xindeco.business;
  2.   
  3.   import java.io.*;
  4.   import java.sql.*;
  5.   import java.util.*;
  6.   import javax.sql.*;
  7.   
  8.   import com.xindeco.common.dbconn.DbConn;
  9.   
  10.   publicclass CertificateDAO extends DAO
  11.   {
  12.   
  13.   public NationDAO(DataSource ds){
  14.   super(ds);
  15.   }
  16.   
  17.   publicList findCertificateList(int offset,int limit)throwsSQLException
  18.   {
  19.   int countRows = 0 ;
  20.   ArrayList list = null ;
  21.   Connection conn = null;
  22.   PreparedStatement pstmt = null;
  23.   ResultSet rs = null;
  24.   try
  25.   {
  26.   conn = ds.getConnection();
  27.   String sql =
  28.   "SELECT certificateID, certificateCode,certificateName,photoURL,"
  29.   + "description,graduateID FROM TCertificate " ;
  30.   pstmt = conn.prepareStatement(sql);
  31.   rs = pstmt.executeQuery();
  32.   /*对游标进行处理,rsHandler 方法在父类DAO中*/
  33.   this.rsHandler(rs,offset,limit);
  34.   if(rs != null && rs.next())
  35.   {
  36.   list = newArrayList() ;
  37.   do
  38.   {
  39.   countRows++ ;
  40.   list.add(rs2VO (rs)) ;
  41.   }
  42.   while((countRows++ < limit) && rs.next()) ;
  43.   }
  44.   close(rs);
  45.   close(pstmt);
  46.   }catch(SQLException e){
  47.   close(rs);
  48.   close(pstmt);
  49.   rollback(conn);
  50.   e.printStackTrace();
  51.   }
  52.   finally{
  53.   close(conn);
  54.   }
  55.   return list ;
  56.   }
  57.   
  58.   private CertificateVO rs2VO (ResultSet rs)
  59.   {
  60.   try
  61.   {
  62.   CertificateVO certificateVO = new CertificateVO () ;
  63.   certificateVO.setCertificateID(rs.getInt("certificateID")) ;
  64.   certificateVO.setCertificateCode(rs.getString("certificateCode")) ;
  65.   certificateVO.setCertificateName(rs.getString("certificateName")) ;
  66.   certificateVO.setPhotoURL(rs.getString("photoURL")) ;
  67.   certificateVO.setDescription(rs.getString("description")) ;
  68.   certificateVO.setGraduateID(rs.getInt("graduateID")) ;
  69.   return certificateVO ;
  70.   }
  71.   catch(Exception ex)
  72.   {
  73.   ex.printStackTrace() ;
  74.   returnnull ;
  75.   }
  76.   }
  77.   }
  78.  
  79.  
Parsed in 0.300 seconds, using GeSHi 1.0.7.12

findCertificateList(int offset,int limit)是查得所有要显示的数据,并放入ArrayList中。看过网上有些例子,把数据记录放入ArrayList的动作过程直接在while循环体里完成,如果字段多的话,会造成方法过于宠大,又不美观。 这里,数据记录放入ArrayList的动作过程由rs2VO方法完成,就比较整洁了。另外,if (rs != null && rs.next ()) 配合while ( (countRows++ < limit) && rs.next ()) 是为了程序的健壮性考虑的,稍分析一下不难得出结论。
  
  3、建立控制器组件:CertificateAction.java

				
JavaZoo.com © 2006. Code Language:java.
  1. package com.xindeco.presentation;
  2.   
  3.   import javax.sql.* ;
  4.   import java.util.* ;
  5.   
  6.   import javax.servlet.http.* ;
  7.   import javax.servlet.* ;
  8.   
  9.   import org.apache.struts.action.* ;
  10.   import org.apache.struts.util.* ;
  11.   
  12.   import com.xindeco.common.Pager;
  13.   import com.xindeco.business.graduatedata.CertificateDAO ;
  14.   
  15.   publicclass CertificateAction
  16.   extendsAction
  17.   {
  18.   privatestaticfinalint PAGE_LENGTH = 5 ; //每页显示5条记录
  19.   public ActionForward execute (ActionMapping mapping, Actionform form,
  20.   HttpServletRequest request,
  21.   HttpServletResponse response)
  22.   {
  23.   ActionForward myforward = null ;
  24.   String myaction = mapping.getParameter() ;
  25.   
  26.   if(isCancelled (request))
  27.   {
  28.   return mapping.findForward("failure") ;
  29.   }
  30.   if("".equalsIgnoreCase(myaction))
  31.   {
  32.   myforward = mapping.findForward("failure") ;
  33.   }
  34.   elseif    ("LIST".equalsIgnoreCase(myaction))
  35.   {
  36.   myforward = performList (mapping, form, request, response) ;
  37.   }
  38.   else
  39.   {
  40.   myforward = mapping.findForward("failure") ;
  41.   }
  42.   return myforward ;
  43.   }
  44.   
  45.   private ActionForward performList (ActionMapping mapping,
  46.   Actionform actionform,
  47.   HttpServletRequest request,
  48.   HttpServletResponse response)
  49.   {
  50.   try
  51.   {
  52.   DataSource ds = (DataSource) servlet.getServletContext().getAttribute(Action.DATA_SOURCE_KEY);
  53.   
  54.   CertificateDAO  certificateDAO = new CertificateDAO (ds) ;
  55.   
  56.   int offset = 0;  //翻页时的起始记录所在游标
  57.   int length = PAGE_LENGTH;
  58.   String pageOffset = request.getParameter("pager.offset");
  59.   if(pageOffset == null || pageOffset.equals("")){
  60.   offset = 0;
  61.   }else{
  62.   offset = Integer.parseInt(pageOffset);
  63.   }
  64.   List certificateList = certificateDAO .findCertificateList(offset,length) ;
  65.   int size = certificateDAO.getRows(); // 取得总记录数
  66.   String url = request.getContextPath()+"/"+mapping.getPath()+".do";
  67.   String pagerHeader = Pager.generate(offset, size, length, url); //分页处理
  68.   
  69.   request.setAttribute("pager", pagerHeader) ;
  70.   request.setAttribute("list", certificateList) ;
  71.   }
  72.   catch(Exception e)
  73.   {
  74.   e.printStackTrace();
  75.   return mapping.findForward("error") ;
  76.   }
  77.   return mapping.findForward("success") ;
  78.   }
  79.   
  80.  
  81.  
Parsed in 0.403 seconds, using GeSHi 1.0.7.12

CertificateAction.java主要是把数据从DAO中取出,并放入一个ArrayList 中,然后通过配置文件再软件View的JSP页。
  
  5、建立视图listcertificate.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。

				
JavaZoo.com © 2006. Code Language:xml.
  1. <?xml version="1.0"encoding="UTF-8"?>
  2.   <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
  3.   <struts-config>
  4.   <form-beans>
  5.   <form-beanname="certificateform"type="com.xindeco.presentation.graduatedata.Certificateform"/>
  6.   </form-beans>
  7.   <global-forwards>
  8.   <forwardname="error"path="/error/error.jsp"/>
  9.   </global-forwards>
  10.   <action-mappings>
  11.   <actionname="certificateform"parameter="LIST"path="/graduatedata/list"scope="request"type="com.xindeco.presentation.graduatedata.CertificateAction"validate="true">
  12.   <forwardname="success"path="/graduatedata/listcertificate.jsp"/>
  13.   </action>
  14.   </action-mappings>
  15.   &hellip;&hellip;
  16.   </struts-config>
  17.  
  18.  
Parsed in 0.071 seconds, using GeSHi 1.0.7.12

7、最后当然是最重要的分页代码了:Pager.java

				
JavaZoo.com © 2006. Code Language:java.
  1. package com.xindeco.common;
  2.   
  3.   import java.util.* ;
  4.   publicclass Pager {
  5.   privatestaticint MAX_PAGE_INDEX = 10; //页脚显示多少页
  6.   privatestaticString HEADER = "Result page";
  7.   
  8.   publicstaticString generate(int offset, int length, int size, String url){
  9.   if(length > size){
  10.   String pref;
  11.   if(url.indexOf("?") > -1){
  12.   pref = "&";
  13.   }else{
  14.   pref = "?";
  15.   }
  16.   String header = "<font face='Helvetica' size='-1'>"+HEADER+": ";
  17.   if(offset > 0){
  18.   header += "&<a href=\""+url+pref+"pager.offset="+(offset-size)+"\">[<< Prev]</a>\n";
  19.   }
  20.   int start;
  21.   int radius = MAX_PAGE_INDEX/2*size;
  22.   if(offset < radius){
  23.   start = 0;
  24.   }elseif(offset < length-radius){
  25.   start = offset - radius;
  26.   }else{
  27.   start = (length/size-MAX_PAGE_INDEX)*size;
  28.   }
  29.   for(int i=start;i<length && i < start + MAX_PAGE_INDEX*size;i+=size){
  30.   if(i == offset){
  31.   header += "<b>"+(i/size+1)+"</b>\n";
  32.   }else{
  33.   header += "&<a href=\""+url+pref+"pager.offset="+i+"\">"+(i/size+1)+"</a>\n";
  34.   }
  35.   }
  36.   if(offset < length - size){
  37.   header += "&<a href=\""+url+pref+"pager.offset="+((int)offset+(int)size)+"\">[Next >>]</a>\n";
  38.   }
  39.   header += "</font>";
  40.   return header;
  41.   }else{
  42.   return"";
  43.   }
  44.   }
  45.   }
  46.  
  47.  
Parsed in 0.353 seconds, using GeSHi 1.0.7.12

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

posted on 2006-10-03 21:19 马尔代夫 阅读(312) 评论(0)  编辑  收藏 所属分类: 框架学习Struts