ThreadLocal原理与应用
2013-09-29 13:29
435 查看
ThreadLocal原理与应用
需求:项目中用户需要在敏感的操作上加比较详细的日志,日志的功能在dao根据需求手动写入,主要的问题是原有的接口没有传入request的相关信息,比如用户信息,我想到了 ThreadLocal,因为每个servlet是基于多线程,但是每个request的执行是再一个独立的线程中完成,ThreadLocal正适合了我这种需求,可以用来完成我对这个系统的业务扩展。在比如struts2的ServletActionContext中对request的获取,还有hibernate中对sessin的管理就是基于ThreadLocal来实现。
看了下ThreadLocal的源码,相对简单,主要的思路是在每个Thread中维护一个ThreadLocalMap,调用ThreadLocal的 set(T value)的时候,以当前的ThreadLocal实例为key保存到当前线程的ThreadLocalMap中。
关键源码如下:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
理解了上面的以后,使用起来就方便了。我的地体实现如在
1.在web.xml中配置系统每个请求都经过的过滤器
<filter>
<filter-name>AppRequestFilter</filter-name>
<filter-class>com.clifford.restaurant.AppRequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AppRequestFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>AppRequestFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
2.过滤器实现
public class AppRequestFilter implements Filter{
public void destroy() {
}
public void doFilter(ServletRequest arg0, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = ((HttpServletRequest)arg0);
RequestThreadLocal.setRequestThreadLocal(request);
filterChain.doFilter(request, response);
}
}
3.ThreadLocal相关实现
public class RequestThreadLocal {
private static ThreadLocal<HttpServletRequest> requestThreadLocal = new ThreadLocal<HttpServletRequest>();
public static void setRequestThreadLocal(HttpServletRequest request) {
requestThreadLocal.set(request);
}
public static User getLoginUser() {
HttpServletRequest request = requestThreadLocal.get();
Session session = request==null?null:request.getSession(false);
return session==null?null:(User)session.getAttribute(IConstants.USER_KEY);
}
public static String getRequestIp() {
HttpServletRequest request = requestThreadLocal.get();
return request==null?"":request.getRemoteHost();
}
}
相关文章推荐
- Nessus home与Nexpose community 对比
- 手机与linux双网卡共享上网
- 格创CSDN高校联盟携戴尔课代表宣讲会成功举办
- android 轻松实现在线即时聊天【图片、语音、表情、文字】等!含源码!
- 命名空间
- 关于c++中的静态变量和静态方法
- (转)MVC语法-基础
- 关于图像模糊(blur)的评价及其在人脸识别中影响的方法的资料
- (四) Graphivz 颜色选择
- extjs fileuploadfield bug
- 在Windows Azure上配置VM主备切换(1)——Linux篇
- ActionScript学习笔记(六)——边界处理
- 关闭子页面刷新父页面
- linux内核--进程与线程
- (三) Graphivz 基本图片类型
- mysql常见错误总结
- Linux安装rpm格式的文件
- 字符串中可以使这一组,135.555或者是5654415都行反正中间不能有有英文,如果有就返回false。也不可以使这种格式135.546.546
- 解决教务系统开发思维导图
- HDU 4762 Cut the Cake(公式)