ThreadLocal众所周知的只是在当前线程下共享数据,其实内部是一个map,那么ThreadLocal主要可以再哪些地方用呢,下面我将举一个非常常用的,可以说每个项目中都会使用到,那就是分页:例子如下
当我们在做分页的时候肯定是会在业务层写一个类似方法findAll(,查询参数,int offset,int pageSize),然后Dao层又会出现类似的方法,,如果采用ThreadLocal的话则可省掉分页参数offset,跟pageSize,我们只需要在请求到达Action之前将分页参数存在ThreadLocal中,然后在Dao使用查询语句的时候拿出来,这样可以让你更专注于业务逻辑,在定义接口的时候不再关注过多的分页参数之类杂七杂八的东西,
下面以s2sh为例:
第一步,设计一个SystemContext,用于存放ThreadLocal值,不一定必须得像我这样,可以根据需求自行设计,
package cn.com.leadfar.oa.Utils;
public class SystemContext {
private static ThreadLocal<Integer> offset = new ThreadLocal<Integer>();
private static ThreadLocal<Integer> pagesize =new ThreadLocal<Integer>();
public static int getOffset(){
return offset.get()==null?0:offset.get();
}
public static int getPagesize(){
return pagesize.get()==null?Integer.MAX_VALUE:pagesize.get();
}
public static void setOffset(String _offset){
try{
offset.set(Integer.parseInt(_offset));
}catch(Exception e){
}
}
public static void setPagesize(String _pagesize){
try{
pagesize.set(Integer.parseInt(_pagesize));
}catch(Exception e){
}
}
public static void removeOffset(){
offset.remove();
}
public static void removePagesize(){
pagesize.remove();
}
}
定义一个拦截器:获取页面传过来的分页参数并存到ThreadLocal中:
package cn.com.leadfar.oa.interceptor;
import org.apache.struts2.ServletActionContext;
import cn.com.leadfar.oa.Utils.SystemContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class PagerInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invo) throws Exception {
String offset = ServletActionContext.getRequest().getParameter("iDisplayStart");
String pagesize = ServletActionContext.getRequest().getParameter("iDisplayLength");
try{
SystemContext.setOffset(offset);
SystemContext.setPagesize(pagesize);
return invo.invoke();
}finally{
SystemContext.removeOffset();
SystemContext.removePagesize();
}
}
}
将此拦截器加到配置文件中使用
<interceptor name="pager" class="cn.com.leadfar.oa.interceptor.PagerInterceptor"></interceptor>
<interceptor-stack name="oaStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="pager"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven">
<param name="refreshModelBeforeResult">true</param>
</interceptor-ref>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="oaStack"></default-interceptor-ref>
最后再创建查询语句的时候拿出来,不需要写到方法的参数上了
List datas = getSession().createQuery(hql).setFirstResult(SystemContext.getOffset())
.setMaxResults(SystemContext.getPagesize())
这样就完成了一个ThreadLocal的使用