場景以下:在java後臺處理業務的時候,須要調用當前登陸用戶的一些信息,通常狀況下的作法是,在登陸的時候,把登陸對象放到HttpSession對象中,在須要調用的時候,從request或者session對象中獲取,可是這種方式直適用於servlet或者action中調用,只有此處才能獲取到request或session對象。若是須要在一個被調用的業務類中獲取,則沒法行得通。
java
分析:其實只須要找到一種能夠講request對象緩存,同時又能夠在業務類中獲取,便可解決上述問題。面對此問題,我參考了下OSCHINA的源碼,http://www.oschina.net/code/snippet_12_2 ,其中很關鍵的一段代碼以下:瀏覽器
private final static ThreadLocal<RequestContext> contexts = new ThreadLocal<RequestContext>();
而這個ThreadLocal類到底是幹什麼用的呢,看下面這篇文章:
緩存
http://www.iteye.com/topic/103804
cookie
文章內容將的很清楚,關於ThreadLocal的用法,甚至舉了hibernate中session管理的例子,咋一看,確實很容易搞暈,可是從下面的有一個回覆內容,能夠很清晰的明白這個類能幹嗎:session
或者能夠本身定義一個靜態的map,將當前thread做爲key,建立的session做爲值,put到map中,應該也行,這也是通常人的想法,但事實上,ThreadLocal的實現恰好相反,它是在每一個線程中有一個map,而將ThreadLocal實例做爲key,這樣每一個map中的項數不多,並且當線程銷燬時相應的東西也一塊兒銷燬了,不知道除了這些還有什麼其餘的好處。測試
主要是提供了保持對象的方法和避免參數傳遞的方便的對象訪問方式this
下面是我參考OSCHINA的ThreadLocal作的一個實例,供參考:spa
RequestContext類:.net
package com.xmf.demo.thread; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class RequestContext { private ServletContext context; private HttpSession session; private HttpServletRequest request; private HttpServletResponse response; private Map<String, Cookie> cookies; private final static ThreadLocal<RequestContext> contexts = new ThreadLocal<RequestContext>(); /** * 初始化請求上下文 * @param ctx * @param req * @param res */ public static RequestContext begin(ServletContext ctx, HttpServletRequest req, HttpServletResponse res) { RequestContext rc = new RequestContext(); rc.context = ctx; rc.request = req; rc.response = res; rc.session = req.getSession(false); rc.cookies = new HashMap<String, Cookie>(); Cookie[] cookies = req.getCookies(); if(cookies != null) for(Cookie ck : cookies) { rc.cookies.put(ck.getName(), ck); } contexts.set(rc); return rc; } /** * 獲取當前請求的上下文 * @return */ public static RequestContext get(){ return contexts.get(); } public void end() { this.context = null; this.request = null; this.response = null; this.session = null; this.cookies = null; contexts.remove(); } public ServletContext getContext() { return context; } public void setContext(ServletContext context) { this.context = context; } public HttpSession getSession() { return session; } public void setSession(HttpSession session) { this.session = session; } public HttpServletRequest getRequest() { return request; } public void setRequest(HttpServletRequest request) { this.request = request; } public HttpServletResponse getResponse() { return response; } public void setResponse(HttpServletResponse response) { this.response = response; } public Map<String, Cookie> getCookies() { return cookies; } public void setCookies(Map<String, Cookie> cookies) { this.cookies = cookies; } }
此處是過濾器GlobalFilter的代碼:hibernate
package com.xmf.base.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.xmf.demo.thread.RequestContext; /** * 全局過濾器 */ public class GlobalFilter implements Filter { private ServletContext context; /** * Default constructor. */ public GlobalFilter() { // TODO Auto-generated constructor stub } /** * @see Filter#destroy() */ public void destroy() { RequestContext.get().end();//清除線程變量值 } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse res = (HttpServletResponse)response; RequestContext.begin(this.context, req, res);//初始化線程變量值 chain.doFilter(request, response); } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { } }
下面是servlet類
package com.xmf.demo.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.xmf.demo.test.Test; import com.xmf.demo.thread.RequestContext; /** * Servlet implementation class Request1Servlet */ public class Request1Servlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public Request1Servlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { RequestContext.begin(this.getServletContext(), request, response); Test test = new Test(); System.out.println(test.getPara()); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub } }
最後是業務類:
package com.xmf.demo.test; import com.xmf.demo.thread.RequestContext; /** * 測試業務類 * @author gongstring * @date 2014年6月9日 下午5:40:20 */ public class Test { /** * <p>獲取URL請求中的參數值,若是能夠獲取,則實如今業務類中獲取request對象的需求</p> * @author gongstring * @date 2014年6月9日 下午5:43:11 * @return */ public static String getPara(){ return RequestContext.get().getRequest().getParameter("test"); } }
瀏覽器實例:http://127.0.0.1:8080/demo/rq1?test=ThreadLocalDemo