[转帖]一个高效简洁的Struts分页方法_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 4187 | 回复: 0   主题: [转帖]一个高效简洁的Struts分页方法        下一篇 
white
注册用户
等级:少校
经验:1327
发帖:305
精华:0
注册:2011-7-21
状态:离线
发送短消息息给white 加好友    发送短消息息给white 发消息
发表于: IP:您无权察看 2011-8-26 9:32:04 | [全部帖] [楼主帖] 楼主

一、 开发环境

  我的开发环境是: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 "";  }  }  }

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




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论