TreadLocal同一线程数据共享
使用案例(在购物车页面获取登录用户信息)
使用拦截器
/**
*在执行目标方法之前,判断用户的登录状态。并封装传递给controller目标请求
*
**/
@Component
public class CartInterceptor implements HandlerInterceptor {
public static ThreadLocal<UserInfoTo> threadLocal = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
UserInfoTo userInfoTo = new UserInfoTo();
//正常用户信息存放至session
HttpSession session = request.getSession();
MemberRespVo member = (MemberRespVo) session.getAttribute(AuthServerConstant.LOGIN_USER);
if (member !=null){
//用户登录
userInfoTo.setUserId(member.getId());
}
Cookie[] cookies = request.getCookies();
//临时用户信息存放至cookie
if (cookies!=null && cookies.length>0){
for (Cookie cookie : cookies) {
//user-key
String name = cookie.getName();
if (name.equals(CartConstant.TMP_USER_COOKIE_NAME)){
userInfoTo.setUserKey(cookie.getValue());
userInfoTo.setTempUser(true);
}
}
//如果没有临时用户,创建一个user-key
if (!StringUtils.isEmpty(userInfoTo.getUserKey())){
String uuid = UUID.randomUUID().toString().replace("-","");
userInfoTo.setUserKey(uuid);
}
}
//目标方法执行之前
threadLocal.set(userInfoTo);
return true;
}
/**
* 业务执行之后,分配临时用户,让浏览器保存
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
UserInfoTo userInfoTo = threadLocal.get();
if (!userInfoTo.isTempUser()){
Cookie cookie = new Cookie(CartConstant.TMP_USER_COOKIE_NAME, userInfoTo.getUserKey());
cookie.setDomain("gulimall.com");
cookie.setMaxAge(CartConstant.TMP_USER_COOKIE_TIMEOUT);
response.addCookie(cookie);
}
}
}
要使拦截器生效还需配置WebMvcConfigurer
public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry){ registry.addInterceptor(new CartInterceptor()).addPathPatterns("/**"); } }
在需要用到地方使用拦截器组件.出threadLocal
private BoundHashOperations<String, Object, Object> getCartOps() {
UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
String cartKey = "";
if (userInfoTo.getUserId() != null) {
//gulimall:cart:1
cartKey = CART_PREFIX + userInfoTo.getUserId();
} else {
cartKey = CART_PREFIX + userInfoTo.getUserKey();
}
BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(cartKey);
return operations;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?