ThreadLocal应用之一-----利用拦截器或过滤器设置请求上下文
来源:互联网 发布:项羽 知乎 编辑:程序博客网 时间:2024/06/05 13:23
之前一直使用ThreadLocal进行请求上下文的设置,只知道ThreadLocal是线程安全的每个线程获取的是本线程所对应的值,没有去深入了解ThreadLocal的具体实现,现在翻看转载的博客并参照源码,彻底明白了其原理,记录如下。
ThreadLocal存取原理分析
先看如下业务代码:
/** * 应用基本上下文 * @author rambo.pan */public class HttpContext { /** * 静态变量,作为各个线程中的Map的key,每个HttpContext实例为相应的value */ private static final ThreadLocal<HttpContext> currentContext = new ThreadLocal<HttpContext>(); private boolean isLogin; private String userId; private UserInfo userInfo; private VpalRequestHeader header; private String client; /** * 获取ThreadLocal中当前线程对应的HttpContext实例 * @param throwFlag set方法传入false,当context为空时new一个新实例;get方法传入true,当context为空时throw异常 * @return */ private static HttpContext getContext(boolean throwFlag){ HttpContext context = currentContext.get(); if (context == null) { if (throwFlag) { throw new RuntimeException("context can not be access now"); }else { context = new HttpContext(); } } return context; } /** * 获取ThreadLocal中当前线程对应的HttpContext实例:用户登录标识 * @return */ public static boolean isLogin() { HttpContext context = getContext(true); return context.isLogin; }}
我以前的理解是:ThreadLocal实例是和线程关联的,每个线程有单独的ThreadLocal实例,所以对ThreadLocal定义成static final 感到很不理解,因为这样定义就表明:当HttpContext的字节码被装载入虚拟机的时候,其类变量currentContext就会被初始化且仅初始化一次,那么每个线程用key都是一样的了啊,如此推断每个线程拿到的value也都是一样的了。
实际上,这个理解的前半段是没问题的,偏差出现在后面,key虽然是一样的,但是Map却是每个线程都不一样的。看如下分析:
ThreadLocal的get方法实现:
/***首先获取当前线程*然后获取当前线程对象的属性:ThreadLocalMap*再从该Map中取得value,而key正是ThreadLocal的引用*由此可以很清楚明白,每个线程在ThreadLocal.get()时,所用的Map对象都是不同的,所以尽管key相同,得到的value也是不同的。*/public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue();}
拦截器设置
public class UserContextInterceptor implements HandlerInterceptor{ private Logger logger = LoggerFactory.getLogger(getClass()); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //1.获取header里的参数并设置到ThreadLocal中 VpalRequestHeader header = mapHeader(request); HttpContext.setHeader(header); //2.校验sessionId 合法性 //3.获取并设置用户信息 UserInfo userInfo = getLoginUserInfo(request,response); HttpContext.setUserInfo(userInfo); logger.debug(String.format("请求%s进入",request.getRequestURI())); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { //设置response的Header信息 response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); logger.info("请求%s返回值:%s",request.getRequestURI(),request.getAttribute("result")); }}
0 0
- ThreadLocal应用之一-----利用拦截器或过滤器设置请求上下文
- 应用上下文&请求上下文
- 利用threadLocal 把拦截器中的对象传递到controller或service中
- 分布式应用上下文(Distributed ThreadLocal)
- 拦截器的应用(+过滤器优化)
- 利用ThreadLocal实现全局上下文工具类
- struts2的请求流程,过滤器和拦截器区别
- struts2设置拦截器不拦截某请求
- struts2过滤器与拦截器组合使用,过滤拦截非法请求
- 过滤器,拦截器,监听器具体应用上的区别
- 关于过滤器,拦截器,监听器具体应用上的区别
- 通过ThreadLocal和Filter实现请求上下文【旧】
- 通过ThreadLocal和Filter实现请求上下文【更新】
- 过滤器与拦截器
- struts2拦截器+过滤器
- 过滤器与拦截器
- 过滤器与拦截器
- java 拦截器、过滤器
- AngularJS2 模板语法
- 在windows的java客户端访问虚拟机中的redis
- 操作系统实验——银行家算法
- Yii2中多表关联查询hasOne hasMany
- nexus配置
- ThreadLocal应用之一-----利用拦截器或过滤器设置请求上下文
- Tomcat基于Coyote的连接器源码分析
- c/c++文件读写操作总结
- Gem5在X64架构下运行SPEC2006
- xposed框架 微信群发源码
- Apache OpenNLP
- css中定位中的absolute和relative
- 每日一题(6):
- 计算字符串的宽度、高度