和绝大多数分页一样,本例也是把所有数据查询出来,然后通过
rsHandler
(rs,offset,limit)来取出当前页所该显示的数据,这样做非常消耗系统资源,如果数据库中存在几十万数据,估计服务器成拖拉机了
-
conn = ds.getConnection();
-
-
"SELECT certificateID, certificateCode,certificateName,photoURL,"
-
+ "description,graduateID FROM TCertificate " ;
-
pstmt = conn.prepareStatement(sql);
-
rs = pstmt.executeQuery();
-
/*对游标进行处理,rsHandler 方法在父类DAO中*/
-
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.
-
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;
-
publicclass DAO
-
{
-
protected DataSource ds;
-
/**
-
* 说明:取得当前查询的总记录数
-
*/
-
publicint getRows ()
-
{
-
returnthis.count;
-
}
-
publicvoid 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) ;
-
}
-
}
-
-
{
-
e.printStackTrace() ;
-
}
-
}
-
public DAO(DataSource ds){
-
this.ds = ds;
-
}
-
-
publicvoid setDataSource(DataSource ds){
-
this.ds = ds;
-
}
-
-
-
if(rs != null){
-
try{
-
rs.close();
-
-
}
-
rs = null;
-
}
-
}
-
-
-
if(pstmt != null){
-
try{
-
pstmt.close();
-
-
}
-
pstmt = null;
-
}
-
}
-
-
if(conn != null){
-
try{
-
conn.close();
-
-
e.printStackTrace();
-
}
-
conn = null;
-
}
-
}
-
-
-
if(conn != null){
-
try{
-
conn.rollback();
-
-
e.printStackTrace();
-
}
-
conn = null;
-
}
-
}
-
}
-
-
Parsed in 0.186 seconds, using GeSHi 1.0.7.12
这个类主要是通过子类传进来的先进结果集,取得查询的记录总数,并对数据库连接进行简单的管理。
2)、对数据库进行访问:CertificateDAO.java
JavaZoo.com © 2006. Code Language:java.
-
package com.xindeco.business;
-
-
import java.io.*;
-
import java.sql.*;
-
import java.util.*;
-
import javax.sql.*;
-
-
import com.xindeco.common.dbconn.DbConn;
-
-
publicclass CertificateDAO extends DAO
-
{
-
-
public NationDAO(DataSource ds){
-
super(ds);
-
}
-
-
-
{
-
int countRows = 0 ;
-
-
-
-
-
try
-
{
-
conn = ds.getConnection();
-
-
"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())
-
{
-
-
do
-
{
-
countRows++ ;
-
list.add(rs2VO (rs)) ;
-
}
-
while((countRows++ < limit) && rs.next()) ;
-
}
-
close(rs);
-
close(pstmt);
-
-
close(rs);
-
close(pstmt);
-
rollback(conn);
-
e.printStackTrace();
-
}
-
finally{
-
close(conn);
-
}
-
return list ;
-
}
-
-
-
{
-
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 ;
-
}
-
-
{
-
ex.printStackTrace() ;
-
returnnull ;
-
}
-
}
-
}
-
-
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.
-
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 ;
-
-
publicclass CertificateAction
-
-
{
-
privatestaticfinalint 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") ;
-
}
-
elseif ("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) ;
-
}
-
-
{
-
e.printStackTrace();
-
return mapping.findForward("error") ;
-
}
-
return mapping.findForward("success") ;
-
}
-
-
-
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.
-
<?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-beanname="certificateform"type="com.xindeco.presentation.graduatedata.Certificateform"/>
-
</form-beans>
-
<global-forwards>
-
<forwardname="error"path="/error/error.jsp"/>
-
</global-forwards>
-
<action-mappings>
-
<actionname="certificateform"parameter="LIST"path="/graduatedata/list"scope="request"type="com.xindeco.presentation.graduatedata.CertificateAction"validate="true">
-
<forwardname="success"path="/graduatedata/listcertificate.jsp"/>
-
</action>
-
</action-mappings>
-
……
-
</struts-config>
-
-
Parsed in 0.071 seconds, using GeSHi 1.0.7.12
7、最后当然是最重要的分页代码了:Pager.java
JavaZoo.com © 2006. Code Language:java.
-
package com.xindeco.common;
-
-
import java.util.* ;
-
publicclass Pager {
-
privatestaticint MAX_PAGE_INDEX = 10; //页脚显示多少页
-
privatestaticString HEADER =
"Result page";
-
-
publicstaticString generate
(int offset,
int length,
int size,
String url
){
-
if(length > size){
-
-
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;
-
}elseif(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"";
-
}
-
}
-
}
-
-
Parsed in 0.353 seconds, using GeSHi 1.0.7.12
这部分代码的实现相当简洁,但已经足够完成所需了。
posted on 2006-10-03 21:19
马尔代夫 阅读(312)
评论(0) 编辑 收藏 所属分类:
框架学习 、
Struts