ThreadLocal分页逻辑的封装处理(转)

分页逻辑的封装处理(请参考AbstractManager.java)
ThreadLocal设计模式,线程局部变量,因为每一次请求都对应一个线程,把初始化的分页数据放在这个局部变量中
当用到时,直接从当前线程中获取。原理同HibernateOpenSessionInView.
为避免在Action(呈现层)和Manager(业务逻辑层)之间传递大量的参数,
可以使用ThreadLocal模式来传递分页参数(包括:offset和pagesize)。
-定义:参考SystemContext.java
-往ThreadLocal中赋值:参考PagerFilter.java
-从ThreadLocal中获取分页参数:参考AbstractManager.java

-------------------------------------------------------------
具体代码如下:
1.定义分页数据封装类
package com.feihu.oa.page;
import java.util.List;
public class PagerModel
{
private List datas; // 分页数据列表
private int total; // 查询总记录数
public List getDatas()
{
return datas;
}
public void setDatas(List datas)
{
this.datas = datas;
}
public int getTotal()
{
return total;
}
public void setTotal(int total)
{
this.total = total;
}
}
2.使用ThreadLocal存储分页起始索引记录位置 与 分页页面显示的记录数
package com.feihu.oa.page;
public class SystemContext {
private static ThreadLocal offset = new ThreadLocal(); //记录起始索引位置
private static ThreadLocal pagesize = new ThreadLocal(); //每页显示多少条记录

public static void setOffset(int _offset){
offset.set(_offset);
}

public static int getOffset(){
Integer _offset = (Integer)offset.get();
if(_offset == null){
return 0;
}
return _offset;
}

public static void removeOffset(){
offset.remove();
}

public static void setPagesize(int _pagesize){
pagesize.set(_pagesize);
}

public static int getPagesize(){
Integer _pagesize = (Integer)pagesize.get();
if(_pagesize == null){
return Integer.MAX_VALUE;
}
return _pagesize;
}

public static void removePagesize(){
pagesize.remove();
}
}


3.定义分页逻辑处理封装类AbstractManager.java
--------------------------------------------------------------------------
package com.feihu.dao;

import java.util.List;
import org.hibernate.Query;
import com.feihu.oa.manager.SystemException;
import com.feihu.oa.page.PagerModel;
import com.feihu.oa.page.SystemContext;
public abstract class AbstractManager extends MyDaoSupport
{

public PagerModel searchPaginated(String hql){
return searchPaginated(hql, null);
}

public PagerModel searchPaginated(String hql,Object value){
return searchPaginated(hql, new Object[]{value});
}

public PagerModel searchPaginated(String hql,Object[] values){
return searchPaginated(hql, values, SystemContext.getOffset(), SystemContext.getPagesize());
}

public PagerModel searchPaginated(String hql,int offset,int pagesize){
return searchPaginated(hql, null, offset, pagesize);
}

public PagerModel searchPaginated(String hql,Object value,int offset,int pagesize){
return searchPaginated(hql, new Object[]{value}, offset, pagesize);
}

public PagerModel searchPaginated(String hql,Object[] values,int offset,int pagesize)
{
String countHql = getCountQuery(hql);//使用传递进来的hql语句 构造出查询总记录数的语句
Query query = getSession().createQuery(countHql);//创建hql查询语句,获取总记录数,要用session,getHibernateTemplate没有此方法
if(values != null && values.length > 0)
{
for(int i = 0; i<values.length;i++)
{
query.setParameter(i, values[i]);
}
}
int total = ((Long)query.uniqueResult()).intValue(); //返回结果只有一个时可用此方法

query = getSession().createQuery(hql);//创建查询语句以获取数据集合
query.setFirstResult(offset); //设置hibernate查询开始索引
query.setMaxResults(pagesize); //设置hibernate查询多少条记录
List datas = query.list(); //得到查询数据结果列表集合

PagerModel pm = new PagerModel();
pm.setDatas(datas); //将结果集合设置进 封装好的 分页类
pm.setTotal(total); //将总记录数设置进  分页类
return pm;
}
//
//
private String getCountQuery(String hql)
{
int index = hql.indexOf("from");
if(index!=-1)
{
return "select count(*) " + hql.substring(index);//hql语句中,只有查询总记录数才能用select count(*)这样的写法
}
throw new SystemException("无效的HQL查询语句【"+hql+"】","exception.hql.query");
}
}
++++++++++++++++++++++++++++++++++++
涉及到的其他类如下:
++++++++++++++++++++++++++++++++++++
package com.feihu.dao;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public abstract class MyDaoSupport extends HibernateDaoSupport
{
private SessionFactory mySessionFacotry;
@Resource
public void setMySessionFacotry(SessionFactory sessionFacotry) {
this.mySessionFacotry = sessionFacotry;
}
@PostConstruct
public void injectSessionFactory() {
super.setSessionFactory(mySessionFacotry);
}
}
+++++++++++++++++++++++++++++++
异常信息自定义类
package com.feihu.oa.manager;
public class SystemException extends RuntimeException
{
//异常代码关键字,其值在MessageResources.properties文件定义
String key;
//可以输出一些异常时的参数
Object[] values;
public String getKey()
{
return key;
}
public SystemException(String message,String key)
{
super(message);
this.key=key;
// TODO Auto-generated constructor stub
}
public SystemException()
{
super();
// TODO Auto-generated constructor stub
}
public SystemException(String message, Throwable cause)
{
super(message, cause);
// TODO Auto-generated constructor stub
}
public SystemException(String message)
{
super(message);
// TODO Auto-generated constructor stub
}
public Object[] getValues()
{
return values;
}
public SystemException(Throwable cause)
{
super(cause);
// TODO Auto-generated constructor stub
}
public SystemException(String message,String key,Object[] values)
{
super(message);
this.key = key;
this.values = new Object[]{values};
// TODO Auto-generated constructor stub
}

public SystemException(String message,String key,Object value)
{
super(message);
this.key = key;
this.values = new Object[]{value};
// TODO Auto-generated constructor stub
}
}
++++++++++++++++++++++++++++++++++++++++++
异常信息处理类
package com.feihu.oa.web.action;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ExceptionHandler;
import org.apache.struts.config.ExceptionConfig;
import com.feihu.oa.manager.SystemException;
public class SystemExceptionHandler extends ExceptionHandler
{
@Override
public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException
{
ActionForward forward = null;
if(ae.getPath() != null)
{
forward = new ActionForward(ae.getPath());
}else
{
forward = mapping.getInputForward();
}
if (ex instanceof SystemException)
{
SystemException sysex = (SystemException) ex;
String key = sysex.getKey();
ActionMessage error = null;
if(key==null)
{
error= new ActionMessage(sysex.getKey(),sysex.getMessage());
}else if(sysex.getValues()!=null)
{
error=new ActionMessage(key,sysex.getValues());
}
this.storeException(request, key, error, forward, ae.getScope());

}
return super.execute(ex, ae, mapping, formInstance, request, response);
}
}
++++++++++++++++++++++++++++++++++++++++++
struts-config.xml文件配置
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>

<form-beans>
<form-bean name="orgform"
type="com.feihu.oa.web.formbean.OrgForm">
</form-bean>
</form-beans>
<global-exceptions>
<exception key="errors.detail"
type="com.feihu.oa.manager.SystemException"
path="/common/exception.jsp" scope="request"
handler="com.feihu.oa.web.action.SystemExceptionHandler" />
</global-exceptions>
<action-mappings>
<action path="/org" parameter="method" name="orgform">
<!-- struts异常自动处理 -->
<!-- <exception key="errors.detail" type="java.lang.RuntimeException" path="/common/exception.jsp" scope="request"/>
-->
<!-- 自定义异常 -->
<forward name="index" path="/org/index.jsp"></forward>
<forward name="add_input" path="/org/add_input.jsp"></forward>
<forward name="add_success"
path="/common/pub_add_success.jsp">
</forward>
<forward name="del_success"
path="/common/pub_del_success.jsp">
</forward>
<!-- forward name="exception" path="/common/exception.jsp"></forward>-->
</action>
</action-mappings>
<controller><!-- spring提供的,用于管理 structs请求的action,控制器根据当前的action的path寻找bean,用bean对应的action处理请求 -->
<set-property property="processorClass"
value="org.springframework.web.struts.DelegatingRequestProcessor" />
</controller><!--配置spring控制器-->
<!-- 使用异常机制时要定义这个资源树文件 -->
<message-resources parameter="MessageResources"></message-resources>
</struts-config>

-------------------------------------------------------------------------------
4.定义PagerFilter过滤类,从TreadLocal中获取并设置初始化分页参数

package com.feihu.web.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;
import com.feihu.oa.page.SystemContext;

public class PagerFilter implements Filter {
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 request){
int offset = 0;
try {
offset = Integer.parseInt(request.getParameter("pager.offset"));
} catch (Exception ignore) {
}
return offset;
}

private int getPagesize(HttpServletRequest request){
return 10;
}
public void init(FilterConfig arg0) throws ServletException {
}
}
-----------------------------------------------------------------------------
5.配置web.xml文件,将过滤类加入到web.xml文件中
<filter>
<filter-name>PagerFilter</filter-name>
<filter-class>com.feihu.web.filter.PagerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PagerFilter</filter-name>
<url-pattern>
@Override
protected ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception
{
OrgForm formbean = (OrgForm)form;
Integer parentId = formbean.getParentId();
request.setAttribute("orgs", orgManager.searchOrgs(parentId));

int ppid=0;
if(formbean.getParentId()!=null && formbean.getParentId()>0)
{
Organization org = orgManager.findOrg(formbean.getParentId());
Organization parent = org.getParent();
if(parent!=null)
{
ppid = parent.getId();
}
}
request.setAttribute("ppid", ppid);
return mapping.findForward("index");
}
public ActionForward addInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception
{

return mapping.findForward("add_input");
}
public ActionForward add(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception
{
OrgForm formbean = (OrgForm)form;
Integer parentId=formbean.getParentId();
Organization org = new Organization();
BeanUtils.copyProperties(org, formbean);

return mapping.findForward("add_success");
}
public ActionForward del(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception
{
OrgForm formbean = (OrgForm)form;


return mapping.findForward("del_success");
}
}
ThreadLocalJava中的一个类,用于封装线程局部变量。它提供了一种在多线程环境下,每个线程都可以独立拥有自己的变量副本的机制。 使用ThreadLocal可以解决多线程并发访问共享变量的线程安全问题。它通过为每个线程提供独立的变量副本,确保了每个线程都可以使用自己的变量副本而不会影响其他线程。 ThreadLocal的使用步骤如下: 1. 创建ThreadLocal对象:可以通过直接实例化ThreadLocal类来创建对象。 2. 设置线程局部变量的值:通过调用ThreadLocal对象的set方法来设置当前线程的局部变量值。 3. 获取线程局部变量的值:通过调用ThreadLocal对象的get方法来获取当前线程的局部变量值。 4. 清除线程局部变量的值:通过调用ThreadLocal对象的remove方法来清除当前线程的局部变量值。 封装ThreadLocal可以根据具体需求进行设计,一般可以将其作为一个工具类或者在类中定义成员变量并提供公共方法来操作。在封装时需要考虑到线程安全性和使用便捷性。可以通过提供get和set方法来获取和设置局部变量值,并在方法内部使用ThreadLocal对象来管理线程局部变量。 以下是一个简单的例子,展示了如何封装ThreadLocal: ```java public class ThreadLocalWrapper<T> { private ThreadLocal<T> threadLocal = new ThreadLocal<>(); public void setValue(T value) { threadLocal.set(value); } public T getValue() { return threadLocal.get(); } public void clearValue() { threadLocal.remove(); } } ``` 使用该封装类时,可以通过调用setValue方法设置线程局部变量的值,通过调用getValue方法获取线程局部变量的值,通过调用clearValue方法清除线程局部变量的值。 注意,封装ThreadLocal时需要注意内存泄漏问题,即在不再需要使用ThreadLocal时要及时调用remove方法清除变量值,避免长时间占用内存。另外,多线程环境下的使用要注意线程安全性,可以通过加锁或其他并发控制手段来确保线程安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值