首页 > 开发 > 综合 > 正文

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

2024-07-21 02:15:04
字体:
来源:转载
供稿:网友
  在网上看了几个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 "";
  }
  }
  }
  
  这部分代码的实现相当简洁,但已经足够完成所需了。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表