明天就要离开呆了半年学习的地方:杭州,昨天下午在家没心思看书,看了看以前作的demo,想起来作个分页,最初的设想是作一个可复用的,易扩展的.想了很久以本人目前的技术没法完成,但我又急于想作一下,先去西城广场的新华书店看了一下书:Pojo in Action,最后部分谈到动态分页.觉得实施起来还是太复杂.
走出来好像有点思路了!说实话这是我第一次思考从数据库到页面整个流程的分页方案.以前写ASP时,网上有的是封装好的通用分页函数,这次到JSP着实...,
分页技术,好处就不谈了,关键是只能在Dao层处理数据,如果移到Service层,哪就没有必要分页,个人总结一下:
1:逻辑分页
1.1)JDBC有两种方案:
a:用一个动态临时变量
b:用rs.absolute
rs.absolute((number-1) *Page_Size +1 );
1.2)Hibernate
类似JDBC的第二方案(rs.absolute)
results.setFirstResult((currentCursor-1)*pageSize);
results.setMaxResults(pageSize);
由于原来的demo用的是struts和hibernate,我的最终思路是这样的,
由于从数据库出来的数据是关健,所以第一步从数据开始,上面你已经看到了,在Hibernate中的Query中有两个方法:
public
Query setFirstResult(
int
firstResult)
Set the first row to retrieve. If not set, rows will be retrieved beginnning from row
0
.
Parameters:
firstResult
-
a row number, numbered from
0
public
Query setMaxResults(
int
maxResults)
Set the maximum number of rows to retrieve. If not set, there is no limit to the number of rows retrieved.
Parameters:
maxResults
-
the maximum number of rows
在我原来的Dao实现类中加入以下方法:
public
Collection
<
Book
>
queryAllRecords(
int
currentCursor,
int
pageSize)
...
{
Collection<Book> books=new Vector<Book>();
s=HibernateUtil.getCurrentSession();
t=s.beginTransaction();
Query results=s.createQuery("from Book");
results.setFirstResult((currentCursor-1)*pageSize);
results.setMaxResults(pageSize);
Iterator it=results.list().iterator();
t.commit();
HibernateUtil.closeCurrentSession();
Book b=null;

while(it.hasNext())...{
b=(Book)it.next();
books.add(b);
System.out.println("----query item: "+b.getName());
}
return books;
}
接下来的工作就是在Service层接口中添加相应的调用:
public
interface
BizWorker
<
T
>
...
{
Collection<T> listAllRecord();
void addRecord(T t);
Collection<T> queryAllRecords(int currentCursor,int pageSize);
}
第二步:修改Struts的Action.
一般跳转到分页显示的页面上的连接,可能是这样的
http://localhost:8080/module/list.do
对应的Action原来的代码是:
public
class
BookAction
extends
Action
...
{
BizWorker<Book> bw=new BookService();
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)

throws Exception ...{
// TODO Auto-generated method stub
request.setAttribute("product", bw.listAllRecord());
return mapping.findForward("access");
}
}
让它小变一下:
public
class
BookAction
extends
Action
...
{
BizWorker<Book> bw=new BookService();
CurrentPage pageEntity=null;
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)

throws Exception ...{
//从session中取回page对象实例
pageEntity=(CurrentPage)request.getSession().getAttribute("page");

if(pageEntity==null)...{
//1.说明这是第一次发过来的请求
//用查到的总记录数+页面显示的记录数(5)=创建一个page对象实例
pageEntity=new CurrentPage(new BookService().getTotalNumber(),5);
//保存到session中
request.getSession().setAttribute("page", pageEntity);
}
request.setAttribute("product", bw.queryAllRecords(pageEntity.getCurrentPage(), 5));
return mapping.findForward("access");
}
}
本来想重用该Action,但出于我用JavaScript动态改变连接:
从:
http://localhost:8080/module/list.do
变成
http://localhost:8080/module/list.do?page=param
如果在没有点击分页面板的情况下刷新,会抛出类型转换异常.所以此处又加了一个Action:
public
class
ShowPage
extends
Action
...
{
CurrentPage pageEntity=null;
BizWorker<Book> bw=null;
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)

throws Exception ...{
// TODO Auto-generated method stub
//2:非第-次请求,url中多了page参数
//用传递过来的参数更新session中page的成员:currentpage,的值
pageEntity=(CurrentPage)request.getSession().getAttribute("page");
Integer page=Integer.parseInt(request.getParameter("page"));

if(page==null)...{
page=page.valueOf(1);
}
pageEntity.setCurrentPage(page);
bw=new BookService();
request.setAttribute("product", bw.queryAllRecords(pageEntity.getCurrentPage(), 5));
return mapping.findForward("access");
}
}
原来这两个Action我写在一起,发现异常时,没想到解决方案 ,所以分开了!如果你有好的解决办法可以通知我一下,不盛荣兴.
第三步:一个Pojo实体
用来存储和计算:总页数,当前页数,数据库中的记录数.
构造这个对象要用的两个参数是:
3.1.数据库的总记录数,
必须在第一次请求完成时拿到,也就是这个:
http://localhost:8080/module/list.do
动作执行之前拿到:new BookService().getTotalNumber()
2.每页显示的记录数.
我硬编码了:5
pageEntity=new CurrentPage(new BookService().getTotalNumber(),5);
这行执行后就构造了一个page的实体,并将其保存到session中,我的page Pojo实体源码:
public
class
CurrentPage
implements
java.io.Serializable
...
{
//总数量total
private int total;
//当前数的页数
private int currentPage=1;
//单页的记录数量
private int pageRecords;
//总页数
private int totalPages;

public CurrentPage() ...{}

public CurrentPage(int total, int pageRecords) ...{
super();
this.total = total;
//this.strLink = strLink;
this.pageRecords = pageRecords;
}


public int getTotal() ...{
return total;
}

public void setTotal(int total) ...{
this.total = total;
}


public int getPageRecords() ...{
return pageRecords;
}

public void setPageRecords(int pageRecords) ...{
this.pageRecords = pageRecords;
}

public int getCurrentPage() ...{
return currentPage;
}

public void setCurrentPage(int currentPage) ...{

if(currentPage<=1)...{
this.currentPage=1;

}else if(currentPage>=this.getTotalPages())...{
this.currentPage=this.getTotalPages();

}else...{
this.currentPage = currentPage;
}
}


public int getTotalPages() ...{
int temp=0;

if(this.getTotal()%this.getPageRecords()==0)...{
temp=this.getTotal()/this.getPageRecords();

}else...{
temp=this.getTotal()/this.getPageRecords()+1;
}
return temp;
}
}
最后就只有页面部分了:
1:JavaScript部分.关健的部分
<
script
type
="text/JavaScript"
>
...
//<
function getRequestLink()...{
globalLink=window.location.href;

if(globalLink.lastIndexOf("page=")==-1)...{
globalLink=globalLink.replace("list","showpage")+"?";
}
}

function getRequestPageNumber(param)...{
localLink="";

if(globalLink.lastIndexOf("page=")==-1)...{
localLink=globalLink+"page="+param;

}else...{
localLink=globalLink.replace(/=d/g,"="+param);
}
return localLink;
}
//]]>
</
script
>
说明:
getRequestLink函数的作用是在页面加载完成之后来获得当前的URL地址
<body onload="getRequestLink()">
该URL地址经过替换,把原来的list.do换成showpage.do?
getRequestPageNumber函数的作用是再处理一下替换后的URL,并加上参数page
http://localhost:8080/module/showpage.do?page=param
以下是分页面板的代码:
<
div id
=
"
pagepanel
"
>
<
dl
>
<
dt
>
Results Page:
</
dt
>
<
dd
>
<
a href
=
"
javascript:window.location.replace(getRequestPageNumber(<%=((CurrentPage)request.getSession().getAttribute(
"
page
"
)).getCurrentPage()-1 %>));
"
>
Prev
</
a
>
</
dd
>
<%
CurrentPage p
=
(CurrentPage)request.getSession().getAttribute(
"
page
"
);

for
(
int
i
=
1
;i
<=
p.getTotalPages();i
++
)
...
{%>
<dd>
<a href="javascript:window.location.replace(getRequestPageNumber(<%=i %>));"><%=i %></a>
</dd>
<%}
%>
<
dd
>
<
a href
=
"
javascript:window.location.replace(getRequestPageNumber(<%=((CurrentPage)request.getSession().getAttribute(
"
page
"
)).getCurrentPage()+1 %>));
"
>
Next
</
a
>
</
dd
>
<
dd
><%=
p.getCurrentPage()
%>/<%=
p.getTotalPages()
%></
dd
>
</
dl
>
</
div
>