使用ThreadLocal对分页逻辑的封装处理

ThreadLocal设计模式,线程局部变量,因为每一次请求都对应一个线程,把初始化的分页数据放在这个局部变量中,当用到时,可以直接从当前线程中获取。原理同HibernateOpenSessionInView。

 

为了避免在Action(呈现层)和Manager(业务逻辑层)之间传递大量的参数,所以我们使用ThreadLocal模式来传递分页参数(包括:offset和pagesize)。同时,将分页逻辑做封装抽取出来,也便于Services重复使用。

- 定义:参考SystemContext.java

-往ThreadLocal中赋值:参考PagerFilter.java

-从ThreadLocal中获取分页参数:参考AbstractManager.java


具体代码如下:

1、使用ThreadLocal存储分页起始索引记录位置与分页页面显示的记录数

SystemContext

public classSystemContext {
privatestatic ThreadLocal offset = new ThreadLocal();
privatestatic ThreadLocal pagesize = new ThreadLocal();
 
publicstatic int getOffset(){
Integeros = (Integer)offset.get();
if(os== null){
return0;
}
returnos;
}
 
publicstatic void setOffset(int offsetvalue){
offset.set(offsetvalue);
}
 
publicstatic void removeOffset(){
offset.remove();
}
 
publicstatic int getPagesize(){
Integerps = (Integer)pagesize.get();
if(ps== null){
returnInteger.MAX_VALUE;
}
returnps;
}
 
publicstatic void setPagesize(int pagesizevalue){
pagesize.set(pagesizevalue);
}
 
publicstatic void removePagesize(){
pagesize.remove();
}
 
}



2、定义分页数据封装类

PagerModel

importjava.util.List;
 
public classPagerModel {
 
/**
 * 总记录数
 */
privateint total;
 
/**
 * 当前页结果集
 */
privateList datas;
 
publicList getDatas() {
returndatas;
}
 
publicvoid setDatas(List datas) {
this.datas= datas;
}
 
publicint getTotal() {
returntotal;
}
 
publicvoid setTotal(int total) {
this.total= total;
}
}



3、通过Filter往ThreadLocal中赋值

PagerFilter

importjava.io.IOException;
 
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
 
importcom.bjsxt.oa.SystemContext;
 
public classPagerFilter implements Filter {
 
publicvoid destroy() {
}
 
publicvoid doFilter(ServletRequest request, ServletResponse response,
FilterChainchain) throws IOException, ServletException {
 
HttpServletRequesthttpRequest = (HttpServletRequest)request;
 
SystemContext.setOffset(getOffset(httpRequest));
SystemContext.setPagesize(getPagesize(httpRequest));
 
try{
chain.doFilter(request,response);
}finally{
//清空ThreadLocal中的值
SystemContext.removeOffset();
SystemContext.removePagesize();
}
 
}
 
protectedint getOffset(HttpServletRequest request){
intoffset = 0;
try{
offset= Integer.parseInt(request.getParameter("pager.offset"));
}catch (NumberFormatException ignore) {
}
returnoffset;
}
 
protectedint getPagesize(HttpServletRequest request){
return10;
}
 
publicvoid init(FilterConfig arg0) throws ServletException {
}
 
}



4、定义分页逻辑处理封装类

importjava.util.Iterator;
importjava.util.List;
 
importorg.hibernate.Query;
importorg.springframework.orm.hibernate3.support.HibernateDaoSupport;
 
importcom.bjsxt.oa.PagerModel;
importcom.bjsxt.oa.SystemContext;
importcom.bjsxt.oa.manager.SystemException;
 
public classAbstractManager extends HibernateDaoSupport {
 
//多种重载形式,便于使用
publicPagerModel searchPaginated(String hql){
returnsearchPaginated(hql,null,SystemContext.getOffset(),SystemContext.getPagesize());
}
 
publicPagerModel searchPaginated(String hql,Object param){
returnsearchPaginated(hql,newObject[]{param},SystemContext.getOffset(),SystemContext.getPagesize());
}
 
publicPagerModel searchPaginated(String hql,Object[] params){
returnsearchPaginated(hql,params,SystemContext.getOffset(),SystemContext.getPagesize());
}
 
publicPagerModel searchPaginated(String hql,int offset,int pagesize){
returnsearchPaginated(hql,null,offset,pagesize);
}
 
publicPagerModel searchPaginated(String hql,Object obj,int offset,int pagesize){
returnsearchPaginated(hql,new Object[]{obj},offset,pagesize);
}
 
/**
 * 根据HQL语句进行分页查询
 * @param hql HQL语句
 * @param params HQL语句带的多个参数值
 * @param offset 从第几条记录开始查询
 * @param pagesize 每页显示多少行
 * @return
 */
publicPagerModel searchPaginated(String hql,Object[] params,int offset,int pagesize){
 
// 使用传递进来的hql语句 构造出查询总记录数的语句
StringcountHql = getCountQuery(hql);
//创建hql查询语句,获取总记录数,要用session,getHibernateTemplate没有此方法
Queryquery = getSession().createQuery(countHql);
if(params!= null && params.length > 0){
for(inti=0; i<params.length; i++){
query.setParameter(i,params[i]);
}
}
inttotal = ((Long)query.uniqueResult()).intValue();
 
//创建查询语句以获取数据集合
query= getSession().createQuery(hql);
if(params!= null && params.length > 0){
for(inti=0; i<params.length; i++){
query.setParameter(i,params[i]);
}
}
//设置hibernate查询开始索引
query.setFirstResult(offset);
//设置hibernate查询多少条记录
query.setMaxResults(pagesize);
Listdatas = query.list();
 
//将结果设置到封装好的分页类
PagerModelpm = new PagerModel();
pm.setTotal(total);
pm.setDatas(datas);
returnpm;
}
 
/**
 * 根据HQL语句,获得查找总记录数的HQL语句
 * 如:
 * select ... from Orgnization o where o.parentis null
 * 经过转换,可以得到:
 * select count(*) from Orgnization o whereo.parent is null
 * @param hql
 * @return
 */
privateString getCountQuery(String hql){
intindex = hql.indexOf("from");
if(index!= -1){
return"select count(*) " + hql.substring(index);
}
 
thrownew SystemException("无效的HQL查询语句!");
}
}



5、在Services中使用

public classOrgManagerImpl extends AbstractManager implements OrgManager {
 
publicPagerModel findOrgs(int parentId) {
 
//如果parentId=0,则查找顶级机构列表
if(parentId== 0){
returnsearchPaginated("from Orgnization o where o.parent is null");
}
returnsearchPaginated("from Orgnization o where o.parent.id = ?",parentId);
}
}



在使用中,通过Services中代码,可以发现由于把分页参数(offset、pagesize)放置在了ThreadLocal中,分页查询时,我不再需要在Action(呈现层)和Manager(业务逻辑层)传递分页参数;同时由于AbstractManager的抽象封装,使得Services中的分页查询变得十分简单。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值