【谷粒商城之ThreadLocal用户身份鉴别】

news2024/11/16 11:45:19

本笔记内容为尚硅谷谷粒商城购物车ThreadLocal用户身份鉴别部分

目录

ThreadLocal

1.导入依赖

2.编写配置

3.配置Session 

4.cookie中的user-key说明 

5.编写To与常量

6.编写拦截器

7.添加拦截器的WebConfig配置类

8.Debug测试UserInfoTo中是否有数据 


ThreadLocal


ThreadLocal是一个池,也就是一个Map,存放的是一个线程下的共享数据,即同一个线程共享ThreadLocal中的数据

  • 核心原理是:Map<Thread,Object> threadLocal
  • 在每个线程中都创建了一个 ThreadLocalMap 对象,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。线程之间互不干扰

  • 一次请求进来: 拦截器 ==>> Controller ==>> Service ==>> dao 用的都是同一个线程

 因为拦截器在拦截请求之后会向controller层传递一个UserInfoVo对象,所以为了获取到这个对象,使用ThreadLocal.

所以在拦截器处设置一个静态的ThreadLocal变量:

 public static ThreadLocal<UserInfoTo> threadLocal = new ThreadLocal<UserInfoTo>();

放上数据后就可以传递给后面。

1.导入依赖

导入redis和SpringSession的依赖

  • 将购物车数据存储至Redis中,因此,需要导入Spring整合Redis的依赖。项目上线之后,应该有一个专门的Redis负责存储购物车的数据不应该使用缓存的Redis。
  • 判断用户是否登录则通过判断Session中是否有用户的数据,因此,导入SpringSession的依赖
<!--  Spring整合Redis依赖      -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--  SpringSession的依赖  -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

2.编写配置

# 配置redis
spring.redis.host=192.168.10.10
spring.redis.port=6379

3.配置Session 

@EnableRedisHttpSession
@Configuration
public class GulimallSessionConfig {
    /**
     * 子域问题共享解决
     */
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("gulimall.com");
        cookieSerializer.setCookieName("GULIMALLSESSION");
        return cookieSerializer;
    }
 
    /**
     * 使用json序列化方式来序列化对象数据到redis中
     */
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
       return new GenericJackson2JsonRedisSerializer();
    }
}

4.cookie中的user-key说明 

用户第一次访问购物车的时候为用户颁发一个Cookie(无论是否登录都颁发),cookie的key就叫user-key,value在后台随机生成。同时要设置cookie的过期时间为1个月,还有cookie的作用域。如果手动清除user-key,那么临时购物车的购物项也被清除,所以user-key是用来标识和存储临时购物车数据的。 

 

用户登录之后点击购物车:

访问Session中存储的之前登录的用户信息,并进行用户身份信息(userId)的封装,userId只有登录过的UserInfoTo才有,没登陆过的这个属性值为null,这个属性就是购物车取数据时是取用户购物车还是临时购物车的一个判断。

用户未登录的时候点击购物车:

总之没登陆的用户userId为空,登录的userId有值,但是登不登陆其都有userKey这个属性的值。

Cookie中有 user-key,则表示有临时用户,访问临时用户的购物车信息,把user-key进行用户身份信息的封装

Cookie中没有 user-key,则表示没有临时用户

创建一个临时用户即生成一个name为user-key的cookie临时标识,过期时间为一个月,以后每次浏览器进行访问购物车的时候都会携带user-key。user-key 是用来标识和存储临时购物车数据的,处理完后会返回这个user-key

以上封装好的信息会放进ThreadLocal交给controller进行处理。

 

5.编写To与常量

 

6.编写拦截器

想要使用SpringMVC的拦截器机制,需要先编写一个类,实现HandlerInterceptor接口,根据业务需求重写接口中的方法。

拦截器作用为在调用购物车的接口(实际上拦截器拦截所有请求,不只是购物车的请求)前,先通过 Session 信息判断是否登录,并分别进行用户身份信息的封装,并把user-key放在 Cookie 中。

重写了两个方法:

  • 在执行目标方法之前,判断用户的登录状态,并封装传递给controller目标请求
  • 在执行目标方法之后,若没有临时用户则分配临时用户,让浏览器保存

同时,还要指定拦截器作用在那些请求上。

注意细节:整合SpringSession之后,Session获取数据都是从Redis中获取的

/**
 * 在执行目标方法前,先判断用户登录状态。并封装用户信息传递给Controller
 */
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();
        HttpSession session = request.getSession();
        MemberRespVo member = (MemberRespVo) session.getAttribute(AuthServerConstant.LOGIN_USER);
        if (member != null) {
            //用户登录
            userInfoTo.setUserId(member.getId());
        }
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                String name = cookie.getName();
                if (name.equals(CartConstant.TEMP_USER_COOKIE_NAME)) {
                    userInfoTo.setUserKey(cookie.getValue());
                    userInfoTo.setTempUser(true);
                }
            }
        }
        //目标方法执行之前
        //如果没有临时用户,分配临时用户
        if (StringUtils.isEmpty(userInfoTo.getUserKey())) {
            String uuid = UUID.randomUUID().toString();
            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();
        //如果没有任何信息,创建临时用户,保存cookie
        if (!userInfoTo.isTempUser()) {
            Cookie cookie = new Cookie(CartConstant.TEMP_USER_COOKIE_NAME, userInfoTo.getUserKey());
            cookie.setDomain("gulimall.com");
            //单位秒
            cookie.setMaxAge(CartConstant.TEMP_USER_COOKIE_TIMEOUT);
            response.addCookie(cookie);
        }
    }


}

 

7.添加拦截器的WebConfig配置类

配置拦截器,否则拦截器不生效 

8.Debug测试UserInfoTo中是否有数据 

结束!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/503907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一篇文章搞定time_wait状态的诸多问题

今天聊聊 TIME_WAIT。 如果看过本文之后&#xff0c;你能够对如下“夺命连环问”做到胸中自有沟壑&#xff0c;则我心甚慰&#xff1a; 你觉得一台机器上看到多少 TIME_WAIT 属于不正常状态&#xff1f; 你觉得出现 TIME_WAIT 相关异常后&#xff0c;会对应用程序造成什么样的…

虚拟化技术简介

文章目录 前言一、什么是虚拟化&#xff1f;二、虚拟化的实现条件三、常见的虚拟化软件产品四、如何查看自己电脑是否支持虚拟化 前言 对于虚拟化技术的简单介绍。 一、什么是虚拟化&#xff1f; 将一台物理计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个虚拟机&am…

Oracle DataGuard奇怪的ORA-16494错误

Oracle数据库DataGuard数据无法同步&#xff0c;主库查询v$archive_dest出现ORA-16494错误。 数据库版本Oracle 12.1.0.2.0&#xff1a; SQL> select * from v$version;BANNER --------------------------------------------------------------------------------CON_ID --…

【深度学习】基于华为MindSpore和pytorch的卷积神经网络LeNet5实现MNIST手写识别

1 实验内容简介 1.1 实验目的 &#xff08;1&#xff09;熟练掌握卷积、池化概念&#xff1b; &#xff08;2&#xff09;熟练掌握卷积神经网络的基本原理&#xff1b; &#xff08;3&#xff09;熟练掌握各种卷积神经网络框架单元&#xff1b; &#xff08;4&#xff09;…

【Java笔试强训 32】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;淘宝网店…

初识Vue-事件 样式

目录 事件 事件修饰符 自定义事件 双向绑定 样式style class style Scoped(防止样式污染) 事件 <button click"add($event, 2)">add</button> add(event, num) {event.stopPropagation()// 防止冒泡this.count num; // this在方法里指向当前Vu…

YOLOv5改进系列(1)——添加SE注意力机制

前言 从这篇开始我们进入YOLOv5改进系列。那就先从最简单的添加注意力机制开始吧&#xff01;&#xff08;&#xffe3;︶&#xffe3;&#xff09;↗ 【YOLOv5改进系列】前期回顾&#xff1a; YOLOv5改进系列&#xff08;0&#xff09;——重要性能指标与训练结果评价及分…

Tomcat线程池扩展总结

Tomcat 线程池 前言 最近在压测接口&#xff0c;调线程池参数大小&#xff0c;感觉和预计的不一样。 看了看 tomcat 线程池源码 对比 JDK 线程池源码 源码 构造代码 这里是提交任务 可以看到 这里重写了 TaskQueue 类 可以看到 重写了offer方法 增加了这一行判断&#x…

ePWM模块-时基模块(2)

ePWM模块(2) 时基模块的使用 TBPRD:周期寄存器 (设置的时钟周期存入此,可通过阴影寄存器缓冲后写入,也可通过活动寄存器立即写入) TBCTR:时基计数变值寄存器 (时基当前所计数的值存入,用于和所设定周期值比较) TBPHS:时基相位寄存器 TBSTS:时基状态寄存器 …

Transformer 论文精读——Attention Is All You Need

https://www.bilibili.com/video/BV1pu411o7BE 摘要 序列转录模型是从一个序列生成另一个序列。Transformer 仅利用注意力机制&#xff08;attention&#xff09;&#xff0c;并且在机器翻译领域取得很好的成功。 结论 Transformer 重要贡献之一提出&#xff1a;multi-head…

C++实现二分查找(力扣题目704)

题目要求&#xff1a;给定一个n个元素的&#xff08;升序&#xff09;整型数组nums和一个目标值target&#xff0c;写一个函数搜索nums中的target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回-1 示例 输入: nums [-1,0,3,5,9,12] target 9 输出: 4 解释: 9 出现在…

Coursera—Andrew Ng机器学习—课程笔记 Lecture 3_Linear Algebra Review

3.1 矩阵和向量   参考视频: 3 - 1 - Matrices and Vectors (9 min).mkv 3.2 加法和标量乘法 参考视频: 3 - 2 - Addition and Scalar Multiplication (7 min).mkv 3.3 矩阵向量乘法 参考视频: 3 - 3 - Matrix Vector Multiplication (14 min).mkv 3.4 矩阵乘法 参考视频:…

[Pandas] 读取Excel文件

练习数据准备 demo.xlsx demo.xlsx中的工作表Sheet1显示上述的数据&#xff0c;Sheet2没有数据 我们可以使用Pandas中的read_excel()方法读取Excel格式的数据文件&#xff0c;生成DataFrame数据框进行数据分析处理 基本语法格式 import pandas as pd pd.read_excel(io, sheet…

JVM内存模型介绍

JVM(Java Virtual Machine)又被分为三大子系统&#xff0c;类加载子系统&#xff0c;运行时数据区&#xff0c;执行引擎。在这里我们主要讲解一下JVM的运行时数据区&#xff0c;也就是我们常说的JVM存储数据的内存模型。在这里提一点&#xff0c;平常我们常说内存模型&#xff…

行业趣闻 | 在施工现场“打灰”,挺好的?

房地产市场的不景气对土木行业的冲击、某某大学土木工程专业招不到人、某央企施工人员因吐槽土木行业现状而被辞退…… 面对互联网上诸多对土木行业的调侃和流言&#xff0c;许多土木工程专业的同学变得迷茫了。 这个行业的实际情况究竟是怎样的&#xff1f; 图源网络 2018年10…

Auto-GPT:揭示 ChatGPT、GPT-4 和开源 AI 之间的联系

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、什么是Auto-GPT&#xff1f;二、Auto-GPT 是如何工作的&#xff1f;三、Auto-GPT 能做什么&#xff1f;四、谁制造了 Auto-GPT&#xff1f;五、ChatGPT 或 …

DPDK抓包工具dpdk-dumpcap的使用

在进行网络开发中&#xff0c;我们经常会通过抓包来定位分析问题&#xff0c;在不使用DPDK的情况下&#xff0c;Linux系统通常用tcpdump&#xff0c;windows用wireshark&#xff0c;但是如果我们使用了DPDK来收包&#xff0c;就无法用这两个工具来抓包了。 这个时候我们需要用D…

Linux新字符设备驱动实验

1、新字符设备驱动原理 一、分配和释放设备号 使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可&#xff0c;但是这样会 带来两个问题&#xff1a; ①、需要我们事先确定好哪些主设备号没有使用。 ②、会将一个主设备号下的所有次设备号都使用掉&#…

多线程(线程同步和互斥+线程安全+条件变量)

线程互斥 线程互斥&#xff1a; 任何时刻&#xff0c;保证只有一个执行流进入临界区访问临界资源&#xff0c;通常对临界资源起到保护作用 相关概念 临界资源&#xff1a; 一次仅允许一个进程使用的共享资源临界区&#xff1a; 每个线程内部&#xff0c;访问临界资源的代码&am…

信息抽取与命名实体识别:从原理到实现

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…