国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

ThreadLocal應用之一-----利用攔截器或過濾器設置請求上下文

2019-11-08 20:20:53
字體:
來源:轉載
供稿:網友

之前一直使用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")); }}
上一篇:每日一題(6):

下一篇:01ZigBee簡介

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 万盛区| 彭水| 堆龙德庆县| 新巴尔虎右旗| 永顺县| 兴安盟| 武乡县| 神池县| 宜宾市| 永顺县| 五大连池市| 桂平市| 博客| 禄劝| 旺苍县| 柘城县| 阜康市| 衡南县| 碌曲县| 墨竹工卡县| 浠水县| 申扎县| 砀山县| 攀枝花市| 兰考县| 博白县| 万州区| 泾阳县| 河源市| 永修县| 西宁市| 淳化县| 牙克石市| 大同县| 巴里| 铜鼓县| 迁西县| 资溪县| 海林市| 聊城市| 兴业县|