摘要:ssh2框架是现今开发领域最常用的框架之一,而分页显示功能更是程序员必须掌握的需求实现之一。分页功能的实现主要有两种核心方法,一为通过query.setFirstResult();query.setMaxResults(); 来设置,这是基于数据库sql来筛选;二为通过query.scroll();来设置,这是基于内存分页。对于第一种,执行效率比较高,对于第二种选择其他分页数据会比较快。本文主要讨论用前者基于ssh2框架来实现分页功能。
关键词:ssh2、MVC、分页
引言
如今ssh2框架为越来越多程序员认识与青睐,其清晰的分层的概念有助于程序员更好管理系统,并且spring的反转控制使系统的耦合性进一步降低。而对于显示层,我们经常要将表的数据列出、显示出来,然而事实上往往要显示的数据很多,一次性显示在一个页面显得冗余而且效率也很低,因此就有了分页显示的需求了。通过分页显示,页面变得更加整洁,用户可以快速定位自己需要的数据,并且程序效率也会有所提高。
关于此分页功能,结合一些资料进行整合,形成了以下的分页实现。在实现分页功能之前,我们必须先明白实现功能的原理和基本要素。首先,分页的主要要素为总记录数、每页显示数、共几页、当前页。通过dao.findAll()方法可以查找出表的所有记录,通过输出的list.size()便可以知道总记录数。每页显示数为自己确定,结合总记录数便可以确定query.setFirstResult()和query.setMaxResult()的数值,以此来输出确切显示的数据量。然后通过query.setFirstResult()和每页显示数来确定现在处于第几页,再通过现在处于第几页与总页数进行比对来输出分页控制的选项,此便为分页系统的主要思路。本文试图将每页查找的数据量与分页控制的数据整合起来,使分页功能更加好管理。
一、 功能实现
1. 系统分析
本文为了清晰明了,采用了单表逆向工程。关于导入ssh2三大框架的过程已省略。完成后文件分布如下:
如图所示,memberdaoimpl.java即是通过数据库的数据进行计算来输出一些相关的数据,pagebean.java即是用来处理其数据并整合传给service层,service层用来整合两个方法的功能使其方便调用,action作为以对应表来实例化对象并将其传给显示层。
2. 设计过程
(1) 先建立一个MemberDao.java的接口,用来定义需要用到的方法。分别用来统计总行数和一次输出的数据。
package org.ssh.dao;
import java.util.List;
import org.ssh.po.Xsb;
public interface MemberDao {
public List<Xsb> queryForPage(final String hql,final int offset,final int length);
public int getAllRowCount(String hql);
}
(2) 然后创建MemberDaoImpl.java类实现它们。
package org.ssh.dao.impl;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
importorg.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.ssh.dao.MemberDao;
import org.ssh.po.Xsb;
public class MemberDaoImpl extends HibernateDaoSupport implements MemberDao {
@Override
public List<Xsb> queryForPage(Stringhql, intoffset, intlength) {
// TODO Auto-generated method stub
Session session = this.getSession();
Query q =session.createQuery(hql);
q.setFirstResult(offset);
q.setMaxResults(length);
List<Xsb> list = q.list();
session.close();
return list;
}
@Override
public int getAllRowCount(String hql) {
// TODO Auto-generated method stub
return this.getHibernateTemplate().find(hql).size();
}
}
其中hql为查询语句,offset为query的第一个值定位,length为query的个数长度。
(3) 创建一个获取分页信息的bean。
package org.ssh.po;
import java.util.List;
public class PageBean {
private List<Xsb> list;
private int allRow;
private int totalPage;
private int currentPage;
private int pageSize;
private boolean isFirstPage;
private boolean isLastPage;
private boolean hasPreviousPage;
privatebooleanhasNextPage;
其中list用来存放本次输出的数据,allRow表示总行数,totalPage表示总页数,currentPage表示当前页,pageSize表示每页显示的个数,isFirstPage和isLastPage表示是否为第一页和是否为最后一页,hasPreviousPage和hasNextPage表示有无前一页和有无下一页。分别创建它们的getter和setter方法。
public void init(){
this.isFirstPage= isFirstPage;
this.isLastPage= isLastPage;
this.hasPreviousPage= hasPreviousPage;
this.hasNextPage= hasNextPage;
}
public static int countTotalPage(final int pageSize,finalintallRow){
int totalPage = allRow % pageSize==0?allRow /pageSize:allRow / pageSize + 1;
return totalPage;
}
public static int countOffset(final int pageSize,finalintcurrentPage){
final int offset = pageSize*(currentPage-1);
return offset;
}
public static int countCurrentPage(int page){
final int currpage = (page==0?1:page);
return currpage;
}
}
再创建4个方法。init()方法用于初始化设置,countTotalPage(finalint pageSize,finalint allRow)用于计算总页数,countOffset(finalint pageSize,finalint currentPage)用于计算query的第一个数据位置,int countCurrentPage(int page)用于计算当前页。
(4) 操作Xsb,在业务逻辑层定义方法
package org.ssh.service;
import org.ssh.po.PageBean;
public interface IXsbService {
public PageBean queryForPage(int pageSize,int page);
}
其中pageSize为每页显示的数量,page为第几页。
(5) 实现此方法
package org.ssh.service.impl;
import java.util.List;
import org.ssh.dao.IXsbDAO;
import org.ssh.dao.MemberDao;
import org.ssh.dao.impl.MemberDaoImpl;
import org.ssh.po.PageBean;
importorg.ssh.service.IXsbService;
public class XsbService implements IXsbService {
private IXsbDAO xsbDao;
privateMemberDao memberDao;
需要在spring里注入,并设置好getter和setter方法。
@Override
public PageBean queryForPage(int pageSize, int page) {
// TODO Auto-generated method stub
final String hql = "from Xsb";
int allRow = memberDao.getAllRowCount(hql);
int totalPage = PageBean.countTotalPage(pageSize,allRow);
final int offset = PageBean.countOffset(pageSize, page);
final int length = pageSize;
final int currentPage = PageBean.countCurrentPage(page);
List list = memberDao.queryForPage(hql,offset, length);
PageBean pageBean = new PageBean();
pageBean.setPageSize(pageSize);
pageBean.setCurrentPage(currentPage);
pageBean.setAllRow(allRow);
pageBean.setTotalPage(totalPage);
pageBean.setList(list);
pageBean.init();
return pageBean;
}
最终返回一个封装了分页信息的bean。
(6) 在action中实例化此方法。
public String execute() {
// TODO Auto-generated method stub
this.pageBean = xsbservice.queryForPage(5,page);
this.list = this.pageBean.getList();
return SUCCESS;
}
由此pagebean存放了分页功能的信息,list存放了该页需要显示的内容。
(7) 在显示层输出内容。
<body>
<s:a action="listAction">显示列表</s:a>
<br>
<table>
<tr align="center"bgcolor="silver" >
<th>学号</th><th>姓名</th><th>性别</th>
<th>出生时间</th><th>总学分</th>
</tr>
<s:iterator value="list">
<tr>
<td><s:property value="xh"/></td>
<td><s:property value="xm"/></td>
<td><s:property value="xh"/></td>
<td>
<s:if test="xb==1">
男
</s:if>
<s:else>
女
</s:else>
</td>
<td><s:property value="cssj"/></td>
<td><s:property value="zxf"/></td>
</tr>
</s:iterator>
<s:iterator value="pageBean">
<tr>
<td>共<s:property value="allRow"/>条记录,共<s:property value="totalPage"/>页,当前<s:property value="currentPage"/>页<br>
<s:if test="%{ currentPage==1 }">
第一页上一页</s:if>
<s:else>
<a href="listAction?page=1">第一页</a>
<a href="listAction?page=<s:property value="%{ currentPage-1 }"/>">上一页</a>
</s:else>
<s:if test="%{ currentPage!=totalPage }">
<a href="listAction?page=<s:property value="%{ currentPage+1 }"/>">下一页</a>
<a href="listAction?page=<s:property value="totalPage"/>">最后一页</a>
</s:if>
<s:else>
下一页最后一页
</s:else>
</td>
</tr>
</s:iterator>
</table>
</body>
在jsp页面中list和pagebean内容都用<s:iterator>进行输出,值得注意的是在输出pagebean的时候,采用了<s:if>的判断,用当前页和总页数的数量关系来确定应该输出什么换页功能。
一、总结
分页功能的实现多种多样,笔者的这种实现也是众多优秀实现中的一种,并且在网上得到了很有用的参考后才得到的。此方法整合度较高,对于多个表的逆向工程,只需要在对应的业务逻辑层改写hql语句,简明直接。
参考文献:
[1]from:guangmingfupin http://m.blog.csdn.net/article/details?id=8474151
[2]from:深海骆驼 http://blog.csdn.net/llhwin2010/article/details/7485856
[3]from:johnlee http://459104018-qq-com.iteye.com/blog/467196