ThreadLocal的使用非常簡單
ThreadLocal user = new ThreadLoca();
user.set("username", "jackliu");
String username = user.get("username");

ThreadLocal是維護線程本地變量的一個很好的方法
只有本線程才能獲得本線程內設置的變量,其他線程無法獲取

 /**
     * Returns the value in the current thread's copy of this thread-local
     * variable.  Creates and initializes the copy if this is the first time
     * the thread has called this method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            return (T)map.get(this);

        // Maps are constructed lazily.  if the map for this thread
        // doesn't exist, create it, with this ThreadLocal and its
        // initial value as its only entry.
        T value = initialValue(); //return null
        createMap(t, value);
        return value;
    }

    /**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Many applications will have no need for
     * this functionality, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current threads' copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

    /**
     * Removes the value for this ThreadLocal.  This may help reduce
     * the storage requirements of ThreadLocals.  If this ThreadLocal
     * is accessed again, it will by default have its
     * <tt>initialValue</tt>.
     * @since 1.5
     **/

     public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

    /**
     * Get the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param  t the current thread
     * @return the map
     */
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

    /**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     * @param map the map to store.
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

前段時間有個需求就將是需要一個全局點去獲取登陸用戶的用戶名。
這個需求看起來很簡單,但是卻沒有合適的辦法。
因為如果需要session變量,那么必須在servlet的處理類中,但是很多類并不是servlet
而且也得不到request變量,所以在普通內里面沒有辦法獲取到登陸用戶名
這個時候就需要使用到ThreadLocal類
于是寫了一個Filter。要注意的是因為web服務器針對每個web請求都會啟動一個Thread
所以,每次都需要調用UserUtil.setUserName方法才能保證每個線程都能得到正確的用戶名。


import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.ofbiz.base.util.Debug;
import org.ofbiz.entity.GenericValue;

import com.aicent.ccb.util.StringUtils;
import com.aicent.ccb.util.UserUtil;

public class UserLogFilter implements Filter {
 public static final String module = UserLogFilter.class.getName();

 public void destroy() {

 }

 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {

  HttpServletRequest httpRequest = (HttpServletRequest) request;

  String USERNAME = httpRequest.getParameter("USERNAME");

  if (StringUtils.isValid(USERNAME)) {
   UserUtil.setUserName(USERNAME);
   Debug.logInfo("in request set user name=" + UserUtil.getUserName(),
     module);
  } else {
   HttpSession session = httpRequest.getSession();
   if (null != session) {

    GenericValue userLogin = (GenericValue) session
      .getAttribute("userLogin");
    if (userLogin != null) {
     UserUtil.setUserName(userLogin.getString("userLoginId"));
     Debug.logInfo(
       "in session set user name=" + UserUtil.getUserName(),
       module);
    }
   } else {
    Debug.logInfo("No user in the session", module);
   }
  }

  chain.doFilter(request, response);
 }

 public void init(FilterConfig fc) throws ServletException {

 }

}


public class UserUtil {
  private static final ThreadLocal user = new ThreadLocal() {
         public Object initialValue() {
             return "Unknown User";
         }
     };
  public static void setUserName(String userName){
   user.set(userName);
  }
 
  public static String getUserName(){
   return (String)user.get();
  }
}