SSM框架使用ThreadLocal管理HttpSession
2017-03-24 10:59
127 查看
为了使httpsession在整个项目都可以获取到,比如直接在service层或者dao层调用,不用从controllar传过那么麻烦,这时候可以用ThreadLocal来管理httpsession
简单理解下ThreadLocal
每个线程Thread有一个属性
它是一个map用来存放多个threadlocal
当前线程第一次有threadlocal调用set方法时会创建一个ThreadLocalMap,值写进去,然后和当前线程绑定
之后的threadlocal的set和get方法都先获取当前线程,通过线程拿到ThreadLocalMap,然后通过当前的threadlocal(key)拿到对应的value或者修改value
管理httpsession的总体的思路
因为springmvc每次处理用户的请求,是用的不同的线程(用Thread.currentThread.getId()打印即可发现)
所以用户每次请求的时候,都应该把session绑定到当前线程上,即用ThreadLocal
由于每次请求要先经过filter,所以可以在自定义的filter里面将session放到ThreadLocal里面,这样就可以在后续逻辑中随时调用session了
代码
Session管理类,存放ThreadLocal
Session用户信息类,方便存取用户信息
MyFilter部分代码,将Session中的用户信息放入ThreadLocal
关于自定义的Filter,见前面的博客
http://blog.csdn.net/qc1110/article/details/65442597
在用户登陆的时候将用户信息写入session,如下
顺便对session添加修改user的时候加上个监听,保证threadlocal里的信息和httpsession保持同步
web.xml里配置自己的监听器
到此,ThreadLocal管理HttpSession基本实现了,在项目的任何地方都能直接取到session信息,不用到处传值,降低了耦合度
简单理解下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信息,不用到处传值,降低了耦合度
相关文章推荐
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架——使用MyBatis Generator自动创建代码
- ssm框架的项目,使用maven管理,启动服务器报错
- 昨天学到的使用SSM框架时从mysql中查到数据并展示出来的的两个下拉框
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架中使用Spring的@Transactional注解进行事务管理
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架——使用MyBatis Generator自动创建代码
- JavaEE_Mybatis_SpringMVC_框架整合_lesson1_简单的SSM框架搭建_使用原始Dao开发方式进行测试
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架——使用MyBatis Generator自动创建代码
- SSM框架——使用MyBatis Generator自动创建代码
- MyEclipse使用Maven创建web项目+搭建SSM框架教程
- SSM框架——使用MyBatis Generator自动创建代码,会遇到“前言中不许有内容的错误”
- SSM框架——使用MyBatis Generator自动创建代码