黑马点评回顾 redis实现共享session

文章目录

  • 传统session缺点
  • 整体访问流程
  • 代码实现
    • 生成验证码
    • 登录
  • 问题
    • 具体思路

传统session缺点

传统单体项目一般是把session存入tomcat,但是每个tomcat中都有一份属于自己的session,假设用户第一次访问第一台tomcat,并且把自己的信息存放到第一台服务器的session中,但是第二次这个用户访问到了第二台tomcat,那么在第二台服务器上,肯定没有第一台服务器存放的session,所以此时 整个登录拦截功能就会出现问题。为了解决这个问题,我们用redis作为中间件,把用户的信息存入redis中,这样不同tomcat在检验用户是否登陆时,都向redis请求数据,这样就可以在不同的tomcat进行session共享。

整体访问流程

用户去登录会去校验用户提交的手机号和验证码,是否一致,如果一致,则根据手机号查询用户信息,不存在则新建,最后将用户数据保存到redis,并且生成token作为redis的key,当我们校验用户是否登录时,会去携带着token进行访问,从redis中取出token对应的value,判断是否存在这个数据,如果没有则拦截,如果存在则将其保存到threadLocal中,并且放行。
在这里插入图片描述

代码实现

生成验证码

生成验证码,并把生成的验证码存入redis的代码。

    public Result sendCode(String phone) {// 1.校验手机号if (RegexUtils.isPhoneInvalid(phone)) {// 2.如果不符合,返回错误信息return Result.fail("手机号格式错误!");}// 3.符合,生成验证码String code = RandomUtil.randomNumbers(6);// 4.保存验证码到 sessionstringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);// 5.发送验证码log.debug("发送短信验证码成功,验证码:{}", code);// 返回okreturn Result.ok();}

登录

登陆的功能是前端传来,用户的手机号和验证码,如果手机号和验证码都正确,就判断用户是否存在,存在就登陆,不存在就创建用户,然后登陆,如果手机号或者验证码其中一个不正确,就返回错误。

 public Result login(LoginFormDTO loginForm) {// 1.校验手机号String phone = loginForm.getPhone();if (RegexUtils.isPhoneInvalid(phone)) {// 2.如果不符合,返回错误信息return Result.fail("手机号格式错误!");}// 3.从redis获取验证码并校验String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);String code = loginForm.getCode();if (cacheCode == null || !cacheCode.equals(code)) {// 不一致,报错return Result.fail("验证码错误");}// 4.一致,根据手机号查询用户 select * from tb_user where phone = ?User user = query().eq("phone", phone).one();// 5.判断用户是否存在if (user == null) {// 6.不存在,创建新用户并保存user = createUserWithPhone(phone);}// 7.保存用户信息到 redis中// 7.1.随机生成token,作为登录令牌String token = UUID.randomUUID().toString(true);// 7.2.将User对象转为HashMap存储UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));// 7.3.存储String tokenKey = LOGIN_USER_KEY + token;stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);// 7.4.设置token有效期stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);// 8.返回tokenreturn Result.ok(token);}

问题

上面的代码仍然存在问题,就是session刷新问题,原本利用HttpSession,每次访问就刷新,session维持时间就会刷新,然而我们上面的代码是利用redis作为中间件共享session不能自动刷新,为了解决这个问题,我们需要自己设置拦截器进行手动刷新。

具体思路

首先我们要配置一个拦截器,它把他的优先设为最高,他拦截一切路径,然后它的方法内每次拦截的时候,都会检查redis中是否有session,如果有就刷新session,这样就可以维持session维持的时间。
设置拦截器

public class RefreshTokenInterceptor implements HandlerInterceptor {private StringRedisTemplate stringRedisTemplate;public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.获取请求头中的tokenString token = request.getHeader("authorization");if (StrUtil.isBlank(token)) {return true;}// 2.基于TOKEN获取redis中的用户String key  = LOGIN_USER_KEY + token;Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);// 3.判断用户是否存在if (userMap.isEmpty()) {return true;}// 5.将查询到的hash数据转为UserDTOUserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);// 6.存在,保存用户信息到 ThreadLocalUserHolder.saveUser(userDTO);// 7.刷新token有效期stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES);// 8.放行return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 移除用户UserHolder.removeUser();}
}

添加拦截器

@Configuration
public class MvcConfig implements WebMvcConfigurer {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/shop/**","/voucher/**","/shop-type/**","/upload/**","/blog/hot","/user/code","/user/login"
//                        值越小优先级越高。).order(1);// token刷新的拦截器registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns("/**").order(0);}
}

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

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

相关文章

免费的快速手机文件解压APP,快冲

各位小伙伴们大家好&#xff0c;今天我要介绍一款手机上必备的神奇工具&#xff01;你有没有经常遇到需要解压文件情况呢&#xff1f;还在为不知道用哪个软件而烦恼吗&#xff1f;别担心&#xff0c;我给你带来了解决方案 &#xff0c;就是这一款免费的解压精灵。 解压精灵是一…

【Nginx】使用nginx进行反向代理与负载均衡

使用场景 反向代理&#xff1a;一个网站由许多服务器承载的&#xff0c;网站只暴露一个域名&#xff0c;那么这个域名指向一个代理服务器ip&#xff0c;然后由这台代理服务器转发请求到网站负载的多台服务器中的一台处理。这就需要用到Nginx的反向代理实现了 负载均衡&#xf…

怎么去掉邮件内容中的回车符

上图是Outlook 截图&#xff0c;可见1指向的总有回车符&#xff1b; 故障原因&#xff1a; 不小心误按了箭头4这个选项&#xff1b; 解决方法&#xff1a; 点击2箭头确保tab展开&#xff1b; 点击3以找到箭头4. 取消勾选或者多次点击&#xff0c;即可解决。

单区域OSPF配置

配置命令步骤&#xff1a; 1.使用router ospf 进程ID编号 启用OSPF路由 2.使用network 直连网络地址 反掩码 area 0 将其归于区域0 注意&#xff1a;1.进程ID编号可任意&#xff08;1-65535&#xff09;2.反掩码用4个255相减得到 如下图&#xff0c;根据给出要求配置OSPF单区…

HT8313 D/AB切换 音频功率放大器

HT8313具有AB类和D类的自Y切换功能&#xff0c;在受到D类功放EMI干扰困扰时&#xff0c;可随时切换至AB类音频功放模式&#xff08;此时电荷泵升压功能关闭&#xff09;。 HT8313内部固定28dB增益&#xff0c;内置的关断功能使待机电流Z小化&#xff0c;还集成了输出端过流保护…

JavaEE进阶学习:Spring核心和设计思想

Spring 是什么 我们通常所说的 Spring 指的是 Spring Framework&#xff08;Spring 框架&#xff09;&#xff0c;它是⼀个开源框架&#xff0c;有着活跃而庞大的社区&#xff0c;这就是它之所以能长久不衰的原因。Spring 支持广泛的应用场景&#xff0c;它可以让 Java 企业级…

PP-ChatOCRv2、PP-TSv2、大模型半监督学习工具...PaddleX新特性等你来pick!

小A是一名刚刚毕业的算法工程师&#xff0c;有一天&#xff0c;他被老板安排了一个活&#xff0c;要对一批合同扫描件进行自动化信息抽取&#xff0c;输出结构化的分析报表。OCR问题不大&#xff0c;但是怎么进行批量的结构化信息抽取呢&#xff1f;小A陷入了苦苦思索… 小B是…

Java获取Jar、War包路径,并生成可编辑修改的本地配置文件

前言 本地的可修改配置文件的编写理应是一个很常用的功能&#xff0c;但由于数据库的存在&#xff0c;它鲜少被提及&#xff0c;大多数我们直接存储到数据库中了。 以至于现今&#xff0c;除了没接触数据库的新手时常使用它以外&#xff0c;它没有太多的出场机会。 也因此&am…

Hive数据表操作--学习笔记

1&#xff0c;Hive数据表操作 1&#xff0c;建表语句和内外部表 ①创建内部表 create [external] table [if not exists] 表名( 字段名 字段类型 [comment 注释], 字段名 字段类型 [comment 注释], ... ) [row format delimited fields terminated by 指定分隔符];&#xff0…

后端接口性能优化分析-问题发现问题定义

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&…

使用requests库设置no_proxy选项的方法

问题背景 在使用requests库进行HTTP请求时&#xff0c;如果需要使用爬虫IP服务器&#xff0c;可以通过设置proxies参数来实现。proxies参数是一个字典&#xff0c;其中包含了爬虫IP服务器的地址和端口号。然而&#xff0c;当前的requests库并不支持通过proxies参数来设置no_pr…

【GitLab】-HTTP 500 curl 22 The requested URL returned error: 500~SSH解决

写在前面 本文主要介绍通过SSH的方式拉取GitLab代码。 目录 写在前面一、场景描述二、具体步骤1.环境说明2.生成秘钥3.GitLab添加秘钥4.验证SSH方式4.更改原有HTTP方式为SSH 三、参考资料写在后面系列文章 一、场景描述 之前笔者是通过 HTTP Personal access token 的方式拉取…

持续集成指南:GitHubAction 自动构建+部署AspNetCore项目

前言 之前研究了使用 GitHub Action 自动构建和发布 nuget 包&#xff1a;开发现代化的.NetCore控制台程序&#xff1a;(4)使用GithubAction自动构建以及发布nuget包 现在更进一步&#xff0c;使用 GitHub Action 在其提供的 runner 里构建 docker 镜像&#xff0c;之后提交到阿…

6块钱改变世界,网易和拼多多踏入同一条河流?

年底将至&#xff0c;各种颁奖盛典星光熠熠。如果要给今年深蹲反弹中的互联网大厂颁奖&#xff0c;2023表现最突出的可能是师出同门的兄弟网易和拼多多。 从市场表现来看&#xff0c;两家企业录得今年互联网中概股最高涨幅&#xff0c;被称为“中概股之光”&#xff1a;2023年…

【Spring Cloud】黑马头条 用户服务创建、登录功能实现

点击去看上一篇 一、创建用户 model 1.创建用户数据库库 leadnews_user 核心表 ap_user 建库建表语句 这里一定要使用 navicat&#xff0c;执行SQL 文件&#xff0c;以防止 cmd 中的编码问题 先将 SQL 语句&#xff0c;保存在电脑中&#xff0c;再使用 navicat 打开 CREATE…

华为eNSP综合实验考试

VLAN信息表 设备名称 端口 链路类型 VLAN 参数 HZ-HZCampus-Agg01-S5731 GE0/0/1 Trunk PVID:1 Allow-pass&#xff1a;10 20 Eth-trunk1&#xff08;GE0/0/2,0/0/3,0/0/23&#xff09; Trunk PVID:1 Allow-pass&#xff1a;10 20 GE0/0/24 Access PVID&#xf…

(免费)双相情感障碍筛查MDQ 在线测试双向情感障碍

MDQ用于筛查双相障碍&#xff0c;主要包含13个关于双相障碍症状的是非问题&#xff0c;当前测试采用的量表为2010年杨海晨博士翻译版。该量表为目前世界范围内最常用的双相障碍筛查量表&#xff0c;目前在精神科门诊最为常用的量表之一。 双向情感障碍筛查量表&#xff0c;也叫…

【linux】查看CPU的使用率

命令1&#xff1a;top top 总体系统信息 uptime&#xff1a;系统的运行时间和平均负载。tasks&#xff1a;当前运行的进程和线程数目。CPU&#xff1a;总体 CPU 使用率和各个核心的使用情况。内存&#xff08;Memory&#xff09;&#xff1a;总体内存使用情况、可用内存和缓存…

我记不住的getopt_long的那些参数和返回值

前言&#xff1a;最近在学习面向Linux系统进行C语言的编程&#xff0c;通过查询man手册和查看网络上的各种文章来获取一点点的知识&#xff0c;重点是看完手册还是一脸懵逼&#xff0c;搞不懂手册里面再说啥&#xff0c;而本篇文章将记录一下学习getopt_long的那些参数和返回值…

adb手机调试常用命令

查看手机型号 adb shell getprop ro.product.model 查看电池状况 adb shell dumpsys battery 查看分辨率 adb shell wm size 查看屏幕密度 adb shell wm density 查看显示屏参数 adb shell dumpsys window displays 查看android_id adb shell settings get secure android…