您的位置:首页 > 理论基础 > 计算机网络

SSM框架使用ThreadLocal管理HttpSession

2017-03-24 10:59 127 查看
为了使httpsession在整个项目都可以获取到,比如直接在service层或者dao层调用,不用从controllar传过那么麻烦,这时候可以用ThreadLocal来管理httpsession

简单理解下ThreadLocal

每个线程Thread有一个属性

ThreadLocal.ThreadLocalMap threadLocals = null


它是一个map用来存放多个threadlocal

当前线程第一次有threadlocal调用set方法时会创建一个ThreadLocalMap,值写进去,然后和当前线程绑定

void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}


之后的threadlocal的set和get方法都先获取当前线程,通过线程拿到ThreadLocalMap,然后通过当前的threadlocal(key)拿到对应的value或者修改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 void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}


管理httpsession的总体的思路

因为springmvc每次处理用户的请求,是用的不同的线程(用Thread.currentThread.getId()打印即可发现)

所以用户每次请求的时候,都应该把session绑定到当前线程上,即用ThreadLocal

由于每次请求要先经过filter,所以可以在自定义的filter里面将session放到ThreadLocal里面,这样就可以在后续逻辑中随时调用session了

代码

Session管理类,存放ThreadLocal

public class SysSessionManage {
private static ThreadLocal<SysUser> threadLocal = new ThreadLocal<>();

public static void set(SysUser session){
threadLocal.set(session);
}

public static SysUser get(){
return threadLocal.get();
}

public static void remove(){
threadLocal.remove();
}
}


Session用户信息类,方便存取用户信息

public class SysUser {
private Long userId;
private Stri
b7b6
ng userName;
private String userPassword;

public SysUser() {

}

public SysUser(User u) {
if (u != null) {
this.userId = u.getUserId();
this.userName = u.getName();
this.userPassword = u.getPassword();
}
}

public Long getUserId() {
return userId;
}

public void setUserId(Long userId) {
this.userId = userId;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getUserPassword() {
return userPassword;
}

public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
}


MyFilter部分代码,将Session中的用户信息放入ThreadLocal

private void toDoFilter(boolean isExcept, HttpServletRequest req, HttpServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpSession session = req.getSession();
if (!isExcept) {// 非例外的路径,进行自定义过滤
// 根据session判断用户是否已经登录
if (session == null || session.getAttribute("user") == null) {
resp.sendRedirect("/index.html");// 未登录,则跳转到登录页面
return;
}
}
SysSessionManage.set((SysUser)session.getAttribute("user"));//将session的用户信息放入ThreadLocal
chain.doFilter(req, resp);// 继续执行过滤链,不写则只能得到空白的页面
}


关于自定义的Filter,见前面的博客

http://blog.csdn.net/qc1110/article/details/65442597

在用户登陆的时候将用户信息写入session,如下

@ResponseBody
@RequestMapping(value = "/login", method = RequestMethod.POST)
public JSONObject login(User user, HttpServletRequest request, HttpServletResponse response) {
// 验证用户和密码
User u = userService.login(user);
JSONObject jsonObject = new JSONObject();
if (u != null) {
HttpSession session = request.getSession();
session.setAttribute("user", new SysUser(u));
jsonObject.put("result", Constant.SUCCESS);
} else {
jsonObject.put("result", Constant.FAIL);
}
return jsonObject;
}


顺便对session添加修改user的时候加上个监听,保证threadlocal里的信息和httpsession保持同步

public class SysSessionListener implements HttpSessionAttributeListener{

@Override
public void attributeAdded(HttpSessionBindingEvent event) {
if("user".equals(event.getName())){
SysSessionManage.set((SysUser)event.getValue());
}

}

@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
if("user".equals(event.getName())){
SysSessionManage.remove();
}

}

@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
if("user".equals(event.getName())){
SysSessionManage.set((SysUser)event.getValue());
}

}

}


web.xml里配置自己的监听器

<listener>
<listener-class>com.is.common.listener.SysSessionListener</listener-class>
</listener>


到此,ThreadLocal管理HttpSession基本实现了,在项目的任何地方都能直接取到session信息,不用到处传值,降低了耦合度
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: