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();
}
}