写一个商城的项目,在实现登录功能时,当我点击登录按钮后需要先通过controller跳转到login.check做登录的校验,然后再跳转到index首页,并将用户名显示在首页上。
最开始我直接用 return “/index”,虽然需求可以实现,但是url显示的却是/login.check,这样url就与页面不符,然后就采用 return “redirect:index”,这次虽然url正确了,但是用户名无法显示到首页。后采用拦截器和ThreadLocal的方式实现需求。
(我登录后判断用户是否登录时通过ticket来判断的,并且通过下边方式将ticker放到了全路径中)
Cookie cookie = new Cookie("ticket", map.get("ticket").toString());
cookie.setPath("/");
response.addCookie(cookie);
1、创建一个管理ThreadLocal的类
package com.shop.model;
import org.springframework.stereotype.Component;
@Component
public class HostHolder {
private HostHolder() {}
//member 为我要存储的用户的信息
private static ThreadLocal<Member> members = new ThreadLocal<Member>();
public static Member getMember() {
return (Member)members.get();
}
public static void setMember(Member member) {
members.set(member);
}
public static void clear() {
members.remove();
}
}
2、在拦截器的preHandle方法中将获取到的用户信息存入其中
3、threadLocal的内容,
tomcat底层 每一个请求都是一个线程,如果每一个请求都启动一个线程,性能就会降低,
- 于是就有了线程池,而线程池中的线程并不是真正销毁或真正启动的。
- 也就是说这个请求的线程是个可复用的线程,第二次请求可能还会拿到刚刚的线程,
- 若不清空,里面本身就有member对象,数据会错乱
所以在拦截器的afterCompletion方法中使用HostHolder .clear()进行清空。