透明的分页实现,基于ThreadLocal。采用SSH架构为例执行说明

在ITEye上看了一些查询分页实现,实在不咋的。说说自己的实现,供大家参考。

思路:

1. 使用自定义标签来展示分页并完成分页参数的传递

2. 采用Struts的Interceptor拦截分页参数,保存至ThreadLocal变量。注意每个http request处理完成后一定要清除ThreadLocal。不是用struts的项目可采用Filter等替代此struts拦截器

3. 在Dao层最后执行查询的Query中,去ThreadLocal检查是否有分页参数,即是否需要分页。action, service, 完全不用传递分页参数

====================================================================

最终调用方式举例:

步骤1:

Http Get方式:把此代码插入需要显示分页的地方<app:page href='getUserList.do' /> 。请写明分页请求路径。如:getUserList.do

Http Post方式:把此代码插入需要显示分页的地方<app:page form='useListForm' /> 。请写明提交表单的form的id

步骤2:

Dao层中方法:List results = query.list() 改写成:List result = super.list(query)。在super.list(query)中处理分页查询

只需要如上两部即完成分页的所有过程

====================================================================

伪代码实现:

Struts拦截器(不是struts框架可采用Filter实现)

public class PageInterceptor extends AbstractInterceptor {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        String result = null;
        try {
            HttpServletRequest request = ServletActionContext.getRequest();
            Integer currentPage = getIntegerParameter(request, "page");
            // 是否需要分页, 是则保存参数到ThreadLocal
            if (currentPage != null) {
                Page page = new Page();
                page.setCurrentPage(currentPage);
                ThreadLocalData.setPage(page);
            }
            result = invocation.invoke();
        } finally {
            // 重要: 必须清除此值,否则线程池会拿到错误分页数据
            ThreadLocalData.removePage();
        }
        return result;
    }
   
    private Integer getIntegerParameter(HttpServletRequest request, String name) {
        String value = request.getParameter(name);
        if (value == null) {
            return null;
        } else {
           return Integer.parseInt(value.trim());
        }
    }
}

 

存放分页参数的ThreadLocal

public class ThreadLocalData {
   
    private static final ThreadLocal<Page> PAGE_THREAD_LOCAL = new ThreadLocal<Page>();

    public static Page getPage() {
        return PAGE_THREAD_LOCAL.get();
    }

    public static void setPage(Page page) {
        PAGE_THREAD_LOCAL.set(page);
    }
   
    public static void removePage() {
        PAGE_THREAD_LOCAL.remove();
    }
}

 

BaseDao中填写分页查询函数

public class BaseDao {

    private Session session;
   
    /**
     * 分页查询函数。会检查是否有分页参数,如果有则执行分页查询,否则执行普通查询
     * @param queryString
     * @return
     */
    public List list(Query query) {
        // 检查是否需要分页, 并设置到query对象中
        Page page = ThreadLocalData.getPage();
        if (page != null) {
            // 如果需要查询总记录数,执行下面语句。否则跳过
            String queryString = query.getQueryString();
            int fromIndex = queryString.toLowerCase().indexOf("from");
            Query countQuery = getSession().createQuery("select count(*) " + queryString.substring(fromIndex));
            Integer totalCount = Integer.parseInt(countQuery.uniqueResult().toString());
           
            // 分页查询
            int currentPage = page.getCurrentPage();
            int pageSize = page.getPageSize();
            query.setFirstResult((currentPage - 1) * pageSize);
            query.setMaxResults(pageSize);      
           
            // 计算总页数
            page.setTotalPage(totalCount / pageSize + totalCount % pageSize == 0 ? 0 : 1);
           
            // 重新写入ThreadLocal
            ThreadLocalData.setPage(page);
        }
        List results = query.list();
        return results;
    }

 

 

具体的Dao实现

public class UserDao extends BaseDao {

    @SuppressWarnings("unchecked")
    public List<User> getUserDao() {
        String queryString = "from User where age > ?";
        Query query = getSession().createQuery(queryString);
        query.setParameter(1, 20);
        // 唯一不爽的地方: 不能写query.list()。需要用super.list(query)替代
        return super.list(query);
    }
}

 

分页标签

public class PageTag extends TagSupport {

    /**
     *
     */
    private static final long serialVersionUID = -4863513329378411411L;

    // HttpGet方式分页,传递分页请求路径
    private String href;
    // HttpPost方式分页,传递jsp页面中form id
    private String form;

    @Override
    public int doStartTag() throws JspException {
        JspWriter out = pageContext.getOut();
        // 从ThreadLocal中取出分页参数
        Page page = ThreadLocalData.getPage();
        if (page == null)
            return super.doStartTag();
        try {
            if (StringUtils.isBlank(form)) {
                // HttpGet方式分页。大致代码如下
                // class='style'为交给美工的样式
                out.print("<div class='style'>");
                out.print("<a href='" + href + "?page=" + (page.getCurrentPage() - 1) + "'>上一页</a> <a>当前页</a> <a href='...'>下一页</a>");
                out.print("</div>");
            } else {
                // HttpPost方式分页。大致代码如下
                // class='style'为交给美工的样式
                out.print("<div class='style'>");
                out.print("<a href='javascript:linkTo(" + (page.getCurrentPage() - 1) + "'>上一页</a> <a>当前页</a> <a href='...'>下一页</a>");
                out.print("</div>");
                // 继续输出一段分页用的js脚本。此脚本用了jquery写法
                StringBuffer sb = new StringBuffer();
                sb.append("<script type=\"text/javascript\">");
                sb.append("function linkTo(curPos) {");
                sb.append("if (curPos == '') { return ; } ");
                sb.append("var frm = $(\"#" + getForm() + "\");");
                // 追加分页参数到form表单
                sb.append("$(frm).append(\"<input type='hidden' name='page' value='\"+curPos+\"' />\");");
                sb.append("$(frm).submit();}</script>");
                out.print(sb.toString());
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return super.doStartTag();
    }

    // //
    // Getter Setter 略
}

 

分页标签page.tld

<taglib>
 <tlibversion>1.2</tlibversion>
 <jspversion>1.1</jspversion>
 <shortname>PageTag</shortname>
 <uri>PageTag</uri>
 <tag>
  <name>page</name>
  <tagclass>com.xxx.PageTag</tagclass>
  <attribute>
   <name>href</name>
   <required>false</required>
   <rtexprvalue>true</rtexprvalue>
  </attribute>  
  <attribute>
   <name>form</name>
   <required>false</required>
   <rtexprvalue>true</rtexprvalue>
  </attribute>
 </tag>
</taglib>

 

唯一不爽的地方UserDao需要调用super.list(query), 尝试过继承Hibernate Query对象,复写query.list()方法,在自己的list方法中写分页相关逻辑,没成功。有实现了的同志不妨指点指点。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值