Web应用同一线程内不同架构层次的数据共享
2015-02-11 00:00
483 查看
摘要: 在编写 java web 应用的 Service 层代码时,常常需要根据当前会话用户查询相关的数据,而用户信息一般都是放在 HttpSession中,那么问题来了,如何在 Service层获取会话用户?
在编写java web应用的Service 层代码时,常常需要根据当前会话用户查询相关的数据,而用户信息一般都是放在 HttpSession中,那么问题来了,如何在 Service层获取会话用户?
简单的做法是在 Contrller 层获取会话用户,然后通过参数传递给 Service。那么问题又来了,Service 方法那么多,这种做法太繁琐了,有没有优雅一点的办法?
稍有点经验的大概都知道可以用 ThreadLocal 解决,没错,就是她了,先上代码:
这个 ThreadContext 再配合加一个 Servlet Filter,由 Filter 事先把会话用户放到线程变量里,这样在后续的Controller、Service 甚至是自定义的JSP标签与函数库都可以轻松获取到会话用户信息了,会话用户信息共享的问题至此已解决!
会话用户信息共享只是数据共享的一个方面,在实际的应用中,肯定还有其他数据是需要在线程内共享的,那么我们可以对ThreadContext类进行扩展,代码如下:
以上代码,改进的内容如下:
ThreadLocal的存储类型改为Map,这样就可以储存多个变量了
增加了clear方法,在过滤器的前后执行,及时释放资源,同时避免线程池的数据污染
引入ObjectWrapper,利用泛型机制自动转型
设置时,调用:
ThreadContext.set(new LoginUserWrapper().warp(loginUser));
ThreadContext.set(new MyObjectWrapper().warp(MyObject));
读取时,调用:
LoginUser loginUser = ThreadContext.get(LoginUserWrapper.class);
MyObject myObject = ThreadContext.get(MyObjectWrapper.class);
具体实现可以参考项目:http://git.oschina.net/jlin/delonix
ThreadContext 类:
http://git.oschina.net/jlin/delonix/blob/master/delonix-core/src/main/java/net/gazhi/delonix/core/thread/ThreadContext.java
ResetThreadContextFilter 类:
http://git.oschina.net/jlin/delonix/blob/master/delonix-core/src/main/java/net/gazhi/delonix/core/web/ResetThreadContextFilter.java
在编写java web应用的Service 层代码时,常常需要根据当前会话用户查询相关的数据,而用户信息一般都是放在 HttpSession中,那么问题来了,如何在 Service层获取会话用户?
简单的做法是在 Contrller 层获取会话用户,然后通过参数传递给 Service。那么问题又来了,Service 方法那么多,这种做法太繁琐了,有没有优雅一点的办法?
稍有点经验的大概都知道可以用 ThreadLocal 解决,没错,就是她了,先上代码:
public class ThreadContext { private static final ThreadLocal<LoginUser> loginUserThreadLocal = new ThreadLocal<LoginUser>(); public static void setLoginUser(LoginUser loginUser) { loginUserThreadLocal.set(loginUser); } public static LoginUser getLoginUser() { return loginUserThreadLocal.get(); } }
这个 ThreadContext 再配合加一个 Servlet Filter,由 Filter 事先把会话用户放到线程变量里,这样在后续的Controller、Service 甚至是自定义的JSP标签与函数库都可以轻松获取到会话用户信息了,会话用户信息共享的问题至此已解决!
会话用户信息共享只是数据共享的一个方面,在实际的应用中,肯定还有其他数据是需要在线程内共享的,那么我们可以对ThreadContext类进行扩展,代码如下:
public class ThreadContext { private static final ThreadLocal<Map<Class<ObjectWrapper<?>>, ObjectWrapper<?>>> contextThreadLocal = new ThreadLocal<Map<Class<ObjectWrapper<?>>, ObjectWrapper<?>>>(); public static final void clear() { contextThreadLocal.remove(); } @SuppressWarnings("unchecked") protected static final void set(ObjectWrapper<?> wrapper) { Map<Class<ObjectWrapper<?>>, ObjectWrapper<?>> context = contextThreadLocal.get(); if (context == null) { context = new HashMap<Class<ObjectWrapper<?>>, ObjectWrapper<?>>(); contextThreadLocal.set(context); } context.put((Class<ObjectWrapper<?>>) wrapper.getClass(), wrapper); } @SuppressWarnings("unchecked") protected static final <T> T get(Class<? extends ObjectWrapper<? extends T>> wrapperClass) { Map<Class<ObjectWrapper<?>>, ObjectWrapper<?>> cache = contextThreadLocal.get(); if (cache == null) { return null; } ObjectWrapper<T> wrapper = (ObjectWrapper<T>) cache.get(wrapperClass); return wrapper == null ? null : wrapper.getObj(); } }
public abstract class ObjectWrapper<T> { private T obj; public ObjectWrapper<T> wrap(T obj) { this.obj = obj; return this; } T getObj() { return obj; } }
public class LoginUserWrapper extends ObjectWrapper<LoginUser> { } public class MyObjectWrapper extends ObjectWrapper<MyObject> { }
以上代码,改进的内容如下:
ThreadLocal的存储类型改为Map,这样就可以储存多个变量了
增加了clear方法,在过滤器的前后执行,及时释放资源,同时避免线程池的数据污染
引入ObjectWrapper,利用泛型机制自动转型
设置时,调用:
ThreadContext.set(new LoginUserWrapper().warp(loginUser));
ThreadContext.set(new MyObjectWrapper().warp(MyObject));
读取时,调用:
LoginUser loginUser = ThreadContext.get(LoginUserWrapper.class);
MyObject myObject = ThreadContext.get(MyObjectWrapper.class);
具体实现可以参考项目:http://git.oschina.net/jlin/delonix
ThreadContext 类:
http://git.oschina.net/jlin/delonix/blob/master/delonix-core/src/main/java/net/gazhi/delonix/core/thread/ThreadContext.java
ResetThreadContextFilter 类:
http://git.oschina.net/jlin/delonix/blob/master/delonix-core/src/main/java/net/gazhi/delonix/core/web/ResetThreadContextFilter.java
相关文章推荐
- 在不同的Web应用之间共享数据
- 不同层次组织机构数据分析共享(原)
- 多线程并发库高级应用 之 多个线程之间共享数据的方式探讨
- 同一Tomcat下不同Web应用之间共享Session会话
- 追踪app崩溃率、事件响应链、Run Loop、线程和进程、数据表的优化、动画库、Restful架构、SDWebImage的原理
- Asp.net中处理一个站点不同Web应用共享Session的问题
- 不同层次组织机构数据分析共享
- SharedPreferences之不同应用的数据共享
- Java多线程与并发应用-(6)-多个线程之间共享对象和数据的方式
- 如何在不同的android应用之间共享数据?
- android 利用SharedPreferences 在不同应用之间共享数据
- 多线程并发库高级应用 之 线程范围内共享数据
- Asp.net中处理一个站点不同Web应用共享Session的问题
- 学习笔记4_ServletContext(重要整个Web应用的动态资源之间共享数据)
- Asp.net中处理一个站点不同Web应用共享Session的问题
- 多线程并发库高级应用 之 线程范围内共享数据
- 在不同应用之间共享数据ContentProvider,ContentResolver
- 不同应用共享数据——keychain的使用
- 多线程并发库高级应用 之 线程范围内共享数据
- Android 不同应用通过SharedPreference实现共享数据