很多项目中需要在代码中使用当前登录用户的信息,但是又不方便把保存用户信息的session对象传来传去,这种情况下,就可以考虑使用 ThreadLocal。
ThreadLocal是一个依附于本地线程的变量,按照我的理解,每次对服务器请求,都会使用到一个线程,ThreadLocal的作用就是在这个线程的使用过程中只为这个线程所用。
说说具体如何管理用户session。
现在SSH框架用的比较多,有时在DAO层中需要用到当前用户信息,我们首先定义保存在HttpSession中的用户类,可以是你的用户model,也可以是嵌套了model的包装类,我这里叫UserSession。
在登录方法里将上面定义的用户类对象放入HttpSession中,即:
session.setAttribute("UserSession", userSession);
写一个用于检验用户的filter,并在web.xml中配置,目的是判断用户有没有登录以及登录用户有没有对要访问链接的权限等,每次请求经过filter时如果HttpSession中的UserSession对象存在的话重新设置一下:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
UserSession userSession = (UserSession)request.getSession().getAttribute("UserSession");
if (userSession == null) {
//跳转登录页面
...
} else {
request.getSession().setAttribute("UserSession", userSession);
filterChain.doFilter(req, res);
}
}
然后创建一个类,用于存放ThreadLocal的静态变量:
public class SystemSession {
private static ThreadLocal<UserSession> local = new ThreadLocal<UserSession>();
public static void setUserSession(UserSession session) {
local.set(session);
}
public static UserSession getUserSession() {
return local.get();
}
}
创建一个监听器,并在web.xml中配置,监听HttpSession的属性变化:
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
public void attributeAdded(HttpSessionBindingEvent event) {
if ("UserSession".equals(event.getName())) {
SystemSession.setUserSession((UserSession)event.getValue());
}
}
public void attributeReplaced(HttpSessionBindingEvent event) {
if ("UserSession".equals(event.getName())) {
SystemSession.setUserSession((UserSession)event.getValue());
}
}
}
用户在登录后UserSession对象会放入HttpSession中,触发监听器中的attributeAdded方法,于是UserSession对象同时也会放入ThreadLocal中,登录后每次请求会重新设置UserSession对象,触发监听器的attributeReplaced方法,UserSession对象也会放入ThreadLocal中,在程序中用以下语句即可取得UserSession对象:
SystemSession.getUserSession();