s2sh pager-taglib分页(据用户在下拉列表选择每页显示多少行进行分页)

在s2sh架构中利用pager-taglib、interceptor和ThreadLocal 根据用户需求显示进行分页,在此将实现一个根据用户在下拉列表用选择每页将要显示多少行进行分页,在实现时我将数据结果集的获取与分页参数的设置独立分开,所以在我们页面请求提交到的Action类中并看不到分页参数的踪迹...
声明: pager-taglib组件默认的每页显示数目为10,相应的属性是maxPageItems="10",因此我可以将用户自己的显示行数放在session内,并将其赋值给maxPageItems就可以实现用户自己的分页类型。例如httpRequest.getSession().setAttribute("ps", 10);然后maxPageItems="ps".
关于pager-taglib标签的参数及使用请参考pager-tablib分页http://lzh166.iteye.com/blog/616715
下面开始贴代码了
首先下载pager-taglib-2.0.war ,地址[url=http://jsptags.com/tags/navigation/pager/download.jsp]http://jsptags.com/tags/navigation/pager/download.jsp[/url],然后将lib下面的包lib下的jar包放到自己项目的lib下面。
1、实体类Organization 属性:id、name、description,在这里就不在多描述了。
2、封装类BaseService
public class BaseService extends HibernateDaoSupport {
@Resource //将setSessionFactory()进行重构,注入spring中的sessionFactory
public void setSuperSessionFactory(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}
public List searchByPage(String hql){
return searchByPage(hql, null);
}
public List searchByPage(String hql ,Object param){
return searchByPage(hql,new Object[]{param} ,PagerContext.getOffset(), PagerContext.getPagesize());
}
public List searchByPage(String hql ,Object[] params){
//查询总记录数
String countHql = this.getCountHql(hql);
Query query = this.getSession().createQuery(countHql);
if(params !=null && params.length>0){
for(int i=0;i<params.length;i++){
query.setParameter(i, params[i]);
}
}
int totals = ((Long)(query.uniqueResult())).intValue();

//将总记录数放到ThreadLocal局部变量中
PagerContext.setTotals(totals);
//查询分页结果集数据
query = this.getSession().createQuery(hql);
if(params !=null && params.length>0){
for(int i=0;i<params.length;i++){
query.setParameter(i, params[i]);
}
}
query.setFirstResult(PagerContext.getOffset()); //通过PagerContext得到offset
query.setMaxResults(PagerContext.getPagesize()); //通过PagerContext得到pagesize

List datas = query.list();
return datas;
}
/**
* 根据HQL查询语句,分析得到查询总记录数的查询语句
* 根据HQL语句,获得查找总记录数的HQL语句如:select .... from ...
* 转换为:select count(*) from ....
* @param hql
* @return
*/
private String getCountHql(String hql){
//取得from的位置
int index = hql.toLowerCase().indexOf("from");
if(index != -1){
return "select count(*)"+ hql.substring(index);
}
throw new RuntimeException("无效的查询语句【"+hql+"】");
}
}

3、业务逻辑类:orgServiceImpl
@Service("orgService")		//纳入Spring容器管理
public class OrgServiceImpl extends BaseService{

public List<Organization> searchOrgs(int parentId) {
String hql = "from Organization o where o.parent.id is null";
if(parentId !=0){
hql = "from Organization o where o.parent.id="+parentId;
}
return this.searchByPage(hql);
}
}

4、分页数据类:PagerContext类 利用ThreadLocal方式实现分页传值
//用于得到每页个显示数和用于查询的首记录数以及总记录数
public class PagerContext {
//ThreadLocal 线程局部变量,就是为每一个使用该变量的线程提供一个局部的变量值的副本,每个线程都可以独立的改变该线程的变量副本,
//而不会和其它线程的副本冲突,也就是在分页的页面中用户可以根据自己的设置任意改变每页的显示的记录数而不会影响到其他用户浏览数据显示
private static ThreadLocal<Integer> offset = new ThreadLocal<Integer>();//用于query.setFirstResult(offset)
private static ThreadLocal<Integer> pagesize = new ThreadLocal<Integer>();//每页显示的行数用于 query.setMaxResults(pagesize);

private static ThreadLocal<Integer> totals = new ThreadLocal<Integer>(); //总记录数

public static void setOffset(int value){
offset.set(value); //设置当前线程局部变量offset的值
}
public static int getOffset(){
Integer os = (Integer)offset.get();
if(os ==null){
return 0;
}
return os; //返回当前线程所对应的线程局部变量offset
}
public static void setPagesize(int value){
pagesize.set(value); //设置当前线程局部变量pagesize的值
}
public static int getPagesize(){
Integer ps = (Integer)pagesize.get();
if(ps == null){
return Integer.MAX_VALUE; //如果没有设置pagesize则显示一页
}
return ps; 返回当前线程所对应的线程局部变量pagesize
}
public static void setTotals(int value){
ServletActionContext.getRequest().setAttribute("totals", value);
totals.set(value); //设置当前线程局部变量totals的值
}
public static int getTotals(){
Integer ts = (Integer)totals.get();
if(ts == null){
return 0;
}
return ts; //返回当前线程所对应的线程局部变量totals
}
public static void remove(){
//将当前线程局部变量的值删除,目的是为了减少内存的占用,
offset.remove(); //清除为每个用户分配的副本
pagesize.remove();
totals.remove();
}
}

5、分页拦截器类:PagerInterceptor
public class PagerInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//将请求得到的分页参数设置到ThreadLocal的局部变量中
PagerContext.setTotals(getTotals());
PagerContext.setOffset(getOffset());
PagerContext.setPagesize(getPagesize());
try {
return invocation.invoke();
} finally {
//需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,
PagerContext.remove(); //所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
}
}
private int getTotals() {
int totals = PagerContext.getTotals(); //从PagerContext 中取得总记录数
return totals;
}
private int getOffset(){
int offset = 0;
try { //从request请求中获取当前页查询的首记录数
offset = Integer.parseInt(ServletActionContext.getRequest().getParameter("pager.offset"));//得到标签自己计算出的pager.offset
} catch (Exception e) {
}
return offset;
}
private int getPagesize(){
//从页面中请求中,获取用户设置每页显示记录数,取得pagesize参数的值
String ps = ServletActionContext.getRequest().getParameter("pagesize");
if(ps != null){
try {
Integer pagesize = Integer.parseInt(ps);
ServletActionContext.getRequest().getSession().setAttribute("ps",pagesize);
} catch (Exception e) {
}
}
//从session中获取pagesize参数的值
Integer pagesize = (Integer)ServletActionContext.getRequest().getSession().getAttribute("ps");
//如果为空,则表示用户没有设置就则显示默认每页显示10行,并将其放入session,以便在显示页面赋值给maxPageItems使用
if(pagesize == null){
ServletActionContext.getRequest().getSession().setAttribute("ps", 10);
return 10;
}
return pagesize;
}
}

6、页面请求类:orgAction
@Controller("orgAction")
@Scope("prototype")
public class OrgAction implements ModelDriven {
private Organization org = new Organization();

private int pid; //父机构ID
@Resource
private OrgService orgService;
/**
* 显示列表
*/
public String execute(){
//保持父机构的父亲的ID,为返回留用
int ppid=0;
if(pid!=0){
Organization o = this.orgService.find(pid);
if(o.getParent()!=null){
ppid = o.getParent().getId();
}
}
ActionContext.getContext().put("ppid", ppid);
//获取分页数据后,将其放到PagerModel模型中
List<Organization> orgs = orgService.searchOrgs(pid);
ActionContext.getContext().put("orgs", orgs);
return "default";
}
public void preUpdate(int id) {
//根据ID加载机构信息,并将信息赋值给我们的模型,
//等待ModelDrivenInterceptor去将取出模型中的数据如不为空则压入值栈中
//ModelDrivenInterceptor a = new ModelDrivenInterceptor();
org = this.orgService.find(id);
}
public Organization getModel() {
return org;
}
public Organization getOrg() {
return org;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
}


7、显示页面:list.jsp 部分代码
<%@ taglib prefix="s"  uri="/struts-tags" %>
<%@ taglib prefix="pg" uri="http://jsptags.com/tags/navigation/pager"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
...
<script type="text/javascript">
function selectPagesize(field){
document.location.href = document.all.firstpageurl.href + "&pagesize="+field.value;//得到用户从下拉列表选择的每页显示的行数,并刷新到转到首页
}
</script>
....
<s:if test="!#orgs.isEmpty">
<s:iterator value="#orgs">
<tr bgcolor="#EFF3F7" class="TableBody1" onmouseover="this.bgColor = '#DEE7FF';" onmouseout="this.bgColor='#EFF3F7';">
<td align="center" vAlign="center"><s:property value="id"/></td>
<td align="center" vAlign="center"><a href="org.action?pid=<s:property value="id"/>"><s:property value="name"/></a></td>
<td align="center" vAlign="center"><s:property value="sn"/></td>
<td align="center" vAlign="center"><s:property value="parent.name"/></td>
<td align="center" vAlign="center"><a href="javascript:openWin('org!updateInput.action?id=<s:property value="id"/>','updateorg',600,200);">更新</a> 
<a href="javascript:del('org!del.action?id=<s:property value="id"/>')">删除</a></td>
</tr>
</s:iterator>
</s:if>
<!-- 在列表数据为空的时候,要显示的提示信息 -->
<s:else>
<tr>
<td colspan="7" align="center" bgcolor="#EFF3F7" class="TableBody1" onmouseover="this.bgColor = '#DEE7FF';" onmouseout="this.bgColor='#EFF3F7';">
没有找到相应的记录
</td>
</tr>
</s:else>
.....
<!-- 分页导航条设置 -->
<pg:pager url="org.action" items="${totals}" export="currentPageNumber=pageNumber" maxPageItems="${ps}"> <!-- ${ps}是得到session范围内的每页显示的行数 -->
<pg:param name="pid"/>
<pg:first>
<a href="${pageUrl}" id="firstpageurl">首页</a><!-- 为选择列表后请求提供链接 -->
</pg:first>
<pg:prev>
<a href="${pageUrl}" >前页</a>
</pg:prev>
<pg:pages>
<c:choose>
<c:when test="${currentPageNumber eq pageNumber}">
<font color="red">${pageNumber}</font> <!-- 当前页号不显示链接 -->
</c:when>
<c:otherwise>
<a href="${pageUrl}">${pageNumber}</a>
</c:otherwise>
</c:choose>
</pg:pages>
<pg:next>
<a href="${pageUrl}">后页</a>
</pg:next>
<pg:last>
<a href="${pageUrl}">尾页</a>
</pg:last>
</pg:pager>
<!-- 用户选择每页显示行数下拉列表 -->
每页显示
<select name="pagesize" onchange="go(this);" >
<c:forEach begin="5" end="50" step="5" var="i">
<option value="${i}" <c:if test="${ps eq i }">selected</c:if> >${i}</option>
</c:forEach>
</select>行

分页导航图:
[img]http://dl.iteye.com/upload/attachment/218904/8420fe70-96b2-386d-91ab-bb93639b84b2.jpg[/img]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值