疯狂

STANDING ON THE SHOULDERS OF GIANTS
posts - 481, comments - 486, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

ssh中利用pager-taglib和filter进行分页

Posted on 2007-11-16 18:34 疯狂 阅读(4841) 评论(14)  编辑  收藏

     在ssh架构中利用pager-taglib和filter根据用户需求显示进行分页,在次将实现一个根据用户在下拉类表用选择每页将要显示多少行进行分页
   首先介绍pager-taglib标签:
 pg:pager【这个标签用来设置分页的总体参数】重要参数说明:
 url:分页的链接根地址,pager标签会在这个链接的基础上附加分页参数
 items:总记录数,pager标签正是根据这个值来计算分页参数的//需要给它赋上查询的记录数
 maxPageItems:每页显示的行数,默认为10
 maxIndexPages:在循环输出页码的时候,最大输出多少个页码,默认是10
 
pg:first【第一页的标签】重要参数说明:
 export变量的意义:
 pageUrl - 分页链接URL地址(最重要的export参数)
 pageNumber - 页码
 firstItem - 首页第一行的索引值
 lastItem - 首页最后一行的索引值
pg:pre【上一页标签】重要参数说明:
 export变量的意义:
 pageUrl - 分页链接URL地址(最重要的export参数)
 pageNumber - 页码
 firstItem - 前页第一行的索引值
 lastItem - 前页最后一行的索引值
pg:next【下一页标签】重要参数说明:
 export变量的意义:
 pageUrl - 分页链接URL地址(最重要的export参数)
 pageNumber - 页码
 firstItem - 下页第一行的索引值
 lastItem - 下页最后一行的索引值
pg:last重要参数说明:
 export变量的意义:
 pageUrl - 分页链接URL地址(最重要的export参数)
 pageNumber - 页码
 firstItem - 尾页第一行的索引值
 lastItem - 尾页最后一行的索引值
pg:pages【这个标签用来循环输出页码信息】重要参数说明:
 export变量的意义:
 pageUrl - 分页链接URL地址(最重要的export参数)
 pageNumber - 页码
 firstItem - pageNumber这个页码指定的那一页的第一行的索引值
 lastItem - pageNumber这个页码指定的那一页的最后一行的索引值

       pager-taglib组件默认的每页显示数目为10,相应的属性是maxPageItems="10",因此我可以将用户自己的显示行数放在session内,并将其赋值给maxPageItems就可以实现用户自己的分页类型。例如httpRequest.getSession().setAttribute("ps", 10);然后maxPageItems="ps"
   
下面是一个具体的例子:
       首先下载pager-taglib-2.0.war ,地址http://jsptags.com/tags/navigation/pager/download.jsp,然后将lib下面的包lib下的jar包放到自己项目的lib下面。
    生成测试表:t_person,其中实体类Person类有id,name,phone属性,具体在hibernate配置文件中的配置略..。
    创建PagerModel类用于存放从数据库查询的所有person,和总记录数。代码如下:
 package com.test;
import java.util.List;
public class PagerModel {
private int total;//总记录数
private List datas;//所有用户集合

 ...get和set方法
}

 下面一个类用于得到每页个显示数和用于查询的首记录数

package com.test.filter;

public class SystemContext {
 private static ThreadLocal<Integer> offset = new ThreadLocal<Integer>();//用于query.setFirstResult(offset)
 private static ThreadLocal<Integer> pagesize = new ThreadLocal<Integer>();//pagesize每页显示的行数用于

query.setMaxResults(pagesize);-----ThreadLocal线程局部变量,就是为每一个使用该变量的线程都提供一个变量值的副本,每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突,也就是每一个用户都可以改变自己的每页显示的行数而不会影响到其他人
 
 public static void setOffset(int offsetvalue){
  offset.set(offsetvalue);
 } 
 public static int getOffset(){
  Integer ov = offset.get();
  if(ov == null){
   return 0;
  }
  return ov;
 }
 
 public static void setPagesize(int pagesizevalue){
  pagesize.set(pagesizevalue);
 }
 
 public static int getPagesize(){
  Integer ps = pagesize.get();
  if(ps == null){
   return Integer.MAX_VALUE;//将pagesize设置为无穷大,也就是显示在一页上
  }
  return ps;
 }
        public static void removeOffset(){//清除为每个用户分配的副本
  offset.remove();
 }
        public static void removePagesize(){
  pagesize.remove();
 }
 
}
主要的类PagerFilter:用于设置加载用户自定义的pagesize和offset
package com.test.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;


public class PagerFilter implements Filter {

 public static final String PAGE_SIZE_NAME = "ps";
 
 public void destroy() {
  
 }
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
  
  HttpServletRequest httpRequest = (HttpServletRequest)request;
  //设置分页参数
  SystemContext.setOffset(getOffset(httpRequest));
  SystemContext.setPagesize(getPagesize(httpRequest));
  
  try{
   chain.doFilter(request, response);
  }finally{
   SystemContext.removeOffset();
   SystemContext.removePagesize();
  }  
 } 
 private int getOffset(HttpServletRequest httpRequest){
  int offset = 0;
  try {
   offset = Integer.parseInt(httpRequest.getParameter("pager.offset"));//得到标签自己计算出的pager.offset
  } catch (Exception ignore) {
  }
  return offset;
 } 
 //获取每页显示的行数
 private int getPagesize(HttpServletRequest httpRequest){
  String pageSize = httpRequest.getParameter("pagesize");//得到用户自己的每页显示的行数
  if(pageSize != null){
   Integer ps;
   try {
    ps = Integer.parseInt(pageSize);
    httpRequest.getSession().setAttribute(PAGE_SIZE_NAME, ps);
   } catch (Exception ignore) {

   }
  }
  Integer pagesize = (Integer)httpRequest.getSession().getAttribute(PAGE_SIZE_NAME);
  if(pagesize == null
){//如果用户没有设置就每日显示10行,并将其放入session供以便在显示页面赋值给maxPageItems使用
   httpRequest.getSession().setAttribute(PAGE_SIZE_NAME, 10);
   return 10;
  }else{
   return pagesize;
  }
 }

 public void init(FilterConfig arg0) throws ServletException {
 
 }

}
在web.xml中配置:
<filter>
     <filter-name>pagerfilter</filter-name>
     <filter-class>com.test.filter.PagerFilter</filter-class>
   </filter>
   <filter-mapping>
    <filter-name>pagerfilter</filter-name>
    <url-pattern>/*</url-pattern>
   </filter-mapping>

 建立AbstractManager类用于封装查询数据库的细节,管理类可以通过searchPaginated(String hql)就可以得到PagerModel :

     public class AbstractManager extends HibernateDaoSupport {
 
       public PagerModel searchPaginated(String hql){
  return searchPaginated(hql,offset,pagesize);
 }
 public PagerModel searchPaginated(String hql,int offset,int pagesize){
  
  //获取总记录数
  String countHql = getCountQuery(hql);
  Query query = getSession().createQuery(countHql);
  if(params != null && params.length > 0){
   for(int i=0; i<params.length; i++){
    query.setParameter(i, params[i]);
   }
  }
  int total = ((Long)query.uniqueResult()).intValue();
  
  //获取当前页的结果集
  query = getSession().createQuery(hql);
  if(params != null && params.length > 0){
   for(int i=0; i<params.length; i++){
    query.setParameter(i, params[i]);
   }
  }
  query.setFirstResult(SystemContext.getOffset());//通过SystemContext得到Offset
  query.setMaxResults(SystemContext.getPagesize();//通过SystemContext得到pagesize
  List datas = query.list();
  PagerModel pm = new PagerModel();
  pm.setDatas(datas);
  pm.setTotal(total);
  return pm;
 }
 //根据HQL语句,获得查找总记录数的HQL语句如:select .... from ...转换为:select count(*) from ....
 private String getCountQuery(String hql){
  int index = hql.indexOf("from");
  if(index != -1){
   return "select count(*) " + hql.substring(index);
  }
  throw new SystemException("无效的HQL查询语句!");
 }
}
   //下面是具体管理类//得到分页数据PagerModel:
public class PersonManagerImpl extends AbstractManager implements PersonManager {//PersonManager为一个interface
      public PagerModel searchPersons() {
  PagerModel pm = new PagerModel();
  String hql = "select p from Person p";
  return this.searchPaginated(hql);
 }
}
    创建访问页面index.jsp
主要代码:<a href="person.do">用户分页类表</a>
    相应的action页面:主要代码:

public class PersonAction extends DispatchAction {

 private PersonManager personManager;//利用spring注入person管理类
 @Override
 protected ActionForward unspecified(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception {
  
  PagerModel pm = personManager.searchPersons();
  request.setAttribute("pm", pm);
  return mapping.findForward("index");//通过配置文件转到list.jsp
 }
        public void setPersonManager(PersonManager personManager) {
  this.personManager = personManager;
 }

}
显示页面:list.jsp
<%@ taglib prefix="pg"  uri="http://jsptags.com/tags/navigation/pager" %>//引入
...
<script type="text/javascript">
function selectPagesize(field){
 document.location.href = document.all.firstpageurl.href + "&pagesize="+field.value
;//得到用户从下拉列表选择的每页显的行数,并刷新到转到首页
}
</script>
....

<table>
          <!-- 列表标题栏 -->

       <tr bgcolor="#EFF3F7" class="TableBody1">
       
        <td >姓名</td>
        <td >电话</td>
               </tr>
          <!-- 列表数据栏 -->
          <c:forEach items="${pm.datas }" var="person">
       <tr>
     <td >${person.name }</td>
           <td >${person.phone }</td>
              </tr>
        </c:forEach>
      </table>
      <TABLE>
        <TBODY>
          <TR>
            <TD>
 <!-- 分页导航条 -->
<pg:pager url="person.do" items="${pm.total}" export="currentPageNumber=pageNumber" maxPageItems="${ps}">//得到session范围内的每页显示的行数
 <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="selectPagesize(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>行
      </TD>
          </TR>
        </TBODY>
      </TABLE>

实现图如下:

评论

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2007-11-16 23:05 by 专注JAVA开源项目
收藏

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2007-11-17 07:47 by ltnetwork
写得很好,我用的就是这个分页标签

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2007-11-17 07:53 by ltnetwork
pager-taglib默认的是查找全部记录到内存,这样的话数据量大的话会很累,可不可以限制查询返回的记录数?

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2007-11-17 09:26 by freeman1984
@ltnetwork
pager-taglib并没有和数据库打交道,它只是根据你给它的items(记录总数值)和设置的每页显示的记录数以及它自己计算出的每页的首记录来进行计算分多少页,而items并没有要求和数据库的总记录数对应,比如:你的数据有100条,而你给items设置item=“200”,假如每页显示100条,他就会计算出要显示2页,而不是1页。
它根据pageUrl标签得到页面的url地址,而这个地址例如http://localhost:8888/test/person.do?pager.offset=0就代表第一页,如果你设置的每页显示5行的话第二页的地址就是http://localhost:8888/test/person.do?pager.offset=5,而这个pager.offset(每页首记录)是他自己传递的,真正和数据库打交道的是person.do对应的action以及你的manager做的,你的manager得到每页显示的pagesize和通过httpRequest.getParameter("pager.offset"))得到每页的首记录进行查询分页。

# re: ssh中利用pager-taglib和filter进行分页[未登录]  回复  更多评论   

2007-11-17 09:33 by jurafish
好像不能跳转到制定页面:(

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2007-12-31 02:15 by zhoudq
您好,能把例子发我份吗?谢谢
zhdqCN@gmail.com

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2008-04-15 08:43 by 王建
您好,能把例子发我份吗?谢谢
email : wangjian3q@163.com

# re: ssh中利用pager-taglib和filter进行分页[未登录]  回复  更多评论   

2008-07-23 10:27 by aaa
我想请问一下AbstractManager类中的params数组变量是从哪里来的.从天上飞下来的?

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2008-12-08 14:13 by javaQuestion
感谢你的无私的指导!能否发一份源码给我,十分谢谢!热爱java的人。
E-Mail:lwsletter@126.com

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2009-10-29 19:39 by 无水的鱼
你好 最近在学校学习Hibernate 能发份给我么 感谢!

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2009-10-29 19:40 by 无水的鱼
你好 最近在学校学习Hibernate 能发份给我么 感谢!261630172@qq.com

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2009-11-02 15:59 by 咖啡妆
@无水的鱼
源代码都很久了好像不见了,对不起哦

# re: ssh中利用pager-taglib和filter进行分页  回复  更多评论   

2010-09-27 16:22 by 将计就计
如果有a标签 分页的链接 怎么不让它改变呢

# re: ssh中利用pager-taglib和filter进行分页[未登录]  回复  更多评论   

2011-05-09 14:24 by spring
请问,单击第二页的记录时,怎么还能返回到第二页啊,也就是pager.offset的值应该在action里怎么设置啊

只有注册用户登录后才能发表评论。


网站导航: