MVC拦截器、ThreadLocal来进行登录拦截
MVC拦截器、ThreadLocal来进行登录拦截
- 1. 对登录进行拦截
- 1.1 什么是ThreadLocal
- 1.2 定义UserHolder 类,来封装ThreadLocal方法
- 1.3 拦截器WebMvcConfigurer 的配置
- 1.4 登录的配置,当碰到拦截的方法的时候调用
- 1.5 UserServiceImpl
- 1.6 controller:
1. 对登录进行拦截
1.1 什么是ThreadLocal
ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
详细可以看:https://blog.csdn.net/u010445301/article/details/111322569
1.2 定义UserHolder 类,来封装ThreadLocal方法
package com.hmdp.utils;import com.hmdp.dto.UserDTO;public class UserHolder {private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();public static void saveUser(UserDTO user){//存储值tl.set(user);}public static UserDTO getUser(){ //获得我们存储的值return tl.get();}public static void removeUser(){//移除值tl.remove();}
}
1.3 拦截器WebMvcConfigurer 的配置
package com.hmdp.config;import com.hmdp.utils.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor())//新增一个拦截器.excludePathPatterns(//放行的接口"/blog/hot","/shop/**","/upload/**","/voucher/**","/shop-type/**","/user/code","/user/login");}
}
1.4 登录的配置,当碰到拦截的方法的时候调用
package com.hmdp.utils;import com.hmdp.dto.UserDTO;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.获取sessionHttpSession session = request.getSession();//2.获取session的用户Object user = session.getAttribute("user");/*session.setAttribute("sessionName",Object); //保存//用来设置session值的,sessionName是名称,object是你要保存的对象。session.getAttribute("sessionName"); //取得//用来得到对应名称的session值,即得到object对象,注意需要进行类型转换!
*///3.判断用户是否存在if (user == null) {//4.不存在,拦截 返回401状态码 未授权的意思response.setStatus(401);return false;}//5.存在,保存到ThreadLocal 对ThreadLocal进行了规范和重写。UserHolder.saveUser((UserDTO)user);//把user保存到ThreadLocal,对user进行强转//6.放行return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();//移除用户}
}
1.5 UserServiceImpl
package com.hmdp.service.impl;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RegexUtils;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import javax.servlet.http.HttpSession;/*** <p>* 服务实现类* </p>** @author 虎哥* @since 2021-12-22*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Overridepublic Result sendCode(String phone, HttpSession session) {//1.校验手机号if (RegexUtils.isPhoneInvalid(phone)){//RegexUtils去校验手机号是否无效,再utils中//2.如果不符合,返回错误信息return Result.fail("手机号格式错误");}//3.符合,生成验证码String code = RandomUtil.randomNumbers(6);//生成一个6位的随机数字验证码//4.保存验证码到sessionsession.setAttribute("code",code);//5.发送验证码,如果我们要发送短信的话,需要通过第三方平台,比如阿里云之类的,所以我们直接使用log日志输出log.debug("发送短信验证码成功,验证码:"+ code);//返回okreturn Result.ok();}@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {//1.校验手机号//因为我们需要确定,登录的时候,手机号还是不是一个String phone =loginForm.getPhone();if (RegexUtils.isPhoneInvalid(phone)){//RegexUtils去校验手机号是否无效,再utils中//2.如果不符合,返回错误信息return Result.fail("手机号格式错误");}//2.校验验证码Object CacheCode = session.getAttribute("code");String code = loginForm.getCode();if (CacheCode==null||!CacheCode.toString().equals(code)){//3.不一致,报错return Result.fail("验证码错误");}//4.一致,根据手机号查询用户 select * from tb_user where phone = ? =query,因为,我们在这个类上面extends ServiceImpl<UserMapper, User>,所以可以使用mybatisPlusUser user = query().eq("phone", phone).one();//one()是查询一个,如果查询不到,返回null//5.判断用户是否存在if (user == null) {//6.不存在,创建新用户,保存user = creteUserWithPhone(phone);}//7.保存用户信息到sessionsession.setAttribute("User", BeanUtil.copyProperties(user, UserDTO.class));//将user对象转换成UserDTO对象,再保存到session中return Result.ok();}//每一个session都有一个sessionid,当我们访问tomcat的时候,就已经自动带着了,所以,又sessionId就能知道是哪个用户private User creteUserWithPhone(String phone) {//1.创建用户User user =new User();user.setPhone(phone);user.setNickName("User_"+RandomUtil.randomString(10));//2.保存用户save(user);return user;}
}
1.6 controller:
package com.hmdp.controller;import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.UserInfo;
import com.hmdp.service.IUserInfoService;
import com.hmdp.service.IUserService;
import com.hmdp.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import javax.servlet.http.HttpSession;/*** <p>* 前端控制器* </p>** @author 虎哥* @since 2021-12-22*/
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate IUserService userService;@Resourceprivate IUserInfoService userInfoService;/*** 发送手机验证码*/@PostMapping("code")public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {// TODO 发送短信验证码并保存验证码return userService.sendCode(phone,session);//因为我们的短信验证码要保存在session当中}/*** 登录功能* @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码*/@PostMapping("/login")public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){// 实现登录功能return userService.login(loginForm,session);}/*** 登出功能* @return 无*/@PostMapping("/logout")public Result logout(){// TODO 实现登出功能return Result.fail("功能未完成");}@GetMapping("/me")public Result me(){// 获取当前登录的用户并返回UserDTO user = UserHolder.getUser();return Result.ok((UserDTO)user);}@GetMapping("/info/{id}")public Result info(@PathVariable("id") Long userId){// 查询详情UserInfo info = userInfoService.getById(userId);if (info == null) {// 没有详情,应该是第一次查看详情return Result.ok();}info.setCreateTime(null);info.setUpdateTime(null);// 返回return Result.ok(info);}
}
相关文章:

MVC拦截器、ThreadLocal来进行登录拦截
MVC拦截器、ThreadLocal来进行登录拦截 1. 对登录进行拦截1.1 什么是ThreadLocal1.2 定义UserHolder 类,来封装ThreadLocal方法1.3 拦截器WebMvcConfigurer 的配置1.4 登录的配置,当碰到拦截的方法的时候调用1.5 UserServiceImpl1.6 controllerÿ…...

小程序问题
1.获取节点 wx.createSelectorQuery() wx.createSelectorQuery().in(this) //组件中加in(this),不然获取不到 2.使用实例 wx.createSelectorQuery().in(this).select(#share).fields({node: true,size: true}).exec(async (res) > {const canvas res[0].node;…...

arm 版的 deb、rpm、AppImage 都有什么区别
qq arm 版的 deb、rpm 和 AppImage 格式之间存在几个关键区别。以下是对这些区别的详细解释: 包管理系统与兼容性: deb:是Debian及其衍生发行版(如Ubuntu)中使用的软件包格式。这些系统使用dpkg命令来管理deb包&#…...

docker中mysql设置lower_case_table_names配置的坑
前沿 今天在使用flowable流程框架的时候,遇到一个问题。需要配置MySQL数据库以实现表名大小写不敏感。本以为这是一个简单的任务,却耗费了我两个多小时的时间。 docker容器中修改配置,重启不成功 我们前提是容器中的mysql中已经有很多数据…...

python日志记录工具:loguru日志库使用
文章目录 一、使用loguru1、安装2、简单使用3、详细使用4、工具类(1)logUtil.py(2)测试类(3)效果 参考资料 一、使用loguru 1、安装 pip install loguru2、简单使用 from loguru import logger# 打印到文…...

python入门基础知识·二
""" # Python介绍 # Python注释 # 单行注释: # # 多行注释: r """""" # Python输出和输入 # print: 输出 # input: 输入 ①会让程序暂停,②得到的是字符串内容 int(&…...

深度学习中的正则化技术 - 噪声鲁棒性篇
序言 在深度学习的蓬勃发展中,模型的性能与泛化能力成为了研究者们关注的焦点。然而,实际应用中的数据往往伴随着各种噪声,这些噪声不仅来源于数据采集过程中的硬件限制,还可能由环境干扰、传输错误等因素引入。噪声的存在严重影…...

如何通过 Java 来完成 zip 文件与 rar 文件的解压缩?
目录 一、用到的知识点 二、代码展示(分解版) 三、代码展示(整体版) 一、用到的知识点 1.IO流: Input:输入,通过“输入流”进行文件的读取操作 Output:输出,通过“输出流”进行文件的写入操作 2.文件操作相关: File类ÿ…...

C 语言中的联合(Union)的用途是什么?
🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会! 📙C 语言百万年薪修炼课程 通俗易懂,深入浅出,匠心打磨,死磕细节,6年迭代,看过的人都说好。 文章目…...

汽车电子助力转向系统研究
汽车电子助力转向系统研究 摘要 电子助力转向系统(Electric Power Steering,EPS)是一种利用电动机辅助驾驶员进行车辆转向的系统。相比于传统的液压助力转向系统,EPS具有更高的效率、精确性和可控性。本文将详细探讨EPS的工作原理…...

大数据学习之 scala基础(补充)
scala基础: hello world: 写scala可运行文件的注意事项1、如果一个scala文件要运行,class要改成object2、如果是class,就仅单纯代表一个类,如果是object代表的是单例对象3、scala语法中,一句话结束不需要加分号4、sca…...
正向传播和反向传播
正向传播(Forward Propagation) 正向传播是指将输入数据通过神经网络,计算出预测值的过程。具体步骤如下: 输入层:接受输入数据。隐藏层:每个隐藏层中的神经元接收上一层的输出,进行加权求和&…...

前端文件下载的方式
方式一:a标签直接下载 <a href"链接" >下载</a>一个文件链接(一般是服务器上的某个文件),这个链接一般地址栏输入是预览,不是附件下载 如果想改成附件下载,以下两种方式任选一个均…...

视图库对接系列(GA-T 1400)十六、视图库对接系列(本级)通知(订阅回调)
说明 之前我们实现了订阅接口,其中有一个receiveAddr参数, 这个就是对应的回调的地址。一般情况下对应的是同一个服务。 我们推荐使用http://xxx:xxx/VIID/SubscribeNotifications接口文档 SubscribeNotificationList对象对象如下: 文档中是xml,但实际上目前使用的都是jso…...

Python | Leetcode Python题解之第230题二叉搜索树中第K小的元素
题目: 题解: class AVL:"""平衡二叉搜索树(AVL树):允许重复值"""class Node:"""平衡二叉搜索树结点"""__slots__ ("val", "parent&quo…...

Python酷库之旅-第三方库Pandas(018)
目录 一、用法精讲 44、pandas.crosstab函数 44-1、语法 44-2、参数 44-3、功能 44-4、返回值 44-5、说明 44-6、用法 44-6-1、数据准备 44-6-2、代码示例 44-6-3、结果输出 45、pandas.cut函数 45-1、语法 45-2、参数 45-3、功能 45-4、返回值 45-5、说明 4…...

九科bit-Worker RPA 内容学习
入门阶段, 花时间学习和记忆细枝末节,可能会反而分散新手去理解核心逻辑的精力,并且不常用的知识也很容易被遗忘。 简介: 什么是RPA? RPA(Robotic Process Automation,机器人流程自动化&#x…...

vscode编译环境配置-golang
1. 支持跳转 如果单测函数上方不显示run test | debug test,需要安装Code Debugger(因为以前的go Test Explorer不再被维护了) 2. 单测 指定单个用例测试 go test -v run TestXXXdlv 调试 需要安装匹配的go版本和delve版本(如…...

【JavaEE】网络编程——UDP
🤡🤡🤡个人主页🤡🤡🤡 🤡🤡🤡JavaEE专栏🤡🤡🤡 文章目录 1.数据报套接字(UDP)1.1特点1.2编码1.2.1DatagramSocket1.2.2DatagramPacket…...

JAVA毕业设计147—基于Java+Springboot的手机维修管理系统(源代码+数据库)
基于JavaSpringboot的手机维修管理系统(源代码数据库)147 一、系统介绍 本项目分为用户、管理员、维修员三种角色 1、用户: 注册、登录、新闻公告、售后申请、申请列表、意见反馈、个人信息、密码修改 2、管理员: 用户管理、用户管理、栏目管理、网…...

力扣第228题“汇总区间”
在本篇文章中,我们将详细解读力扣第228题“汇总区间”。通过学习本篇文章,读者将掌握如何遍历和汇总区间,并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释,以便于理解。 问题描述 力扣第228题“汇总区间”描…...

部署大语言模型并对话
在阿里云的https://developer.aliyun.com/adc/scenario/b105013328814fe995c0f091d708d67d 选择函数计算 设置服务器配置 复制公网地址 这个地址不能直接 在返回应用,创建应用LLM 对话页面 Open WebUI 点击下面的创建应用 部署完成后访问域名 打开访问地址...

WebSocket、socket.io-client
WebSocket WebSocket 是一种网络通信协议,它提供了一个在单个长期持久的 TCP 连接上进行全双工(full-duplex)通信的通道。 WebSocket 允许客户端和服务器之间进行双向的数据交换,这意味着服务器可以主动向客户端推送数据&#x…...

Maven 仓库
在 Maven 世界中,任何一个依赖、插件或者项目构建的输出,都可以称为 构件 。 坐标和依赖是构件在 Maven 世界中的逻辑表示方式,构件的物理表示方式是文件,Maven 通过仓库来统一管理这些文件。 任何一个构件都有一组坐标唯一标识。…...

给后台写了一个优雅的自定义风格的数据日志上报页面
highlight: atelier-cave-dark 查看后台数据日志是非常常见的场景,经常看到后台的小伙伴从服务器日志复制一段json数据字符串,然后找一个JSON工具网页打开,在线JSON格式化校验。有的时候,一些业务需要展示mqtt或者socket的实时信息展示,如果不做任何修改直接展示一串字符…...

【React Native优质开源项目】
🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...

Android 自动更新时间的数字时钟 TextClock
TextClock 继承 TextView ,使用方法和 TextView 一样。 它专门用于显示数字时钟,可以自定义显示格式。 只要在布局文件里添加,它会自动更新时间,不需要添加刷新逻辑。 布局文件, <?xml version"1.0"…...

【Linux Git入门】Git的介绍
文章目录 前言git简介git是什么git的作用为什么要学习git安装git总结前言 在现代软件开发中,版本控制系统已经成为了不可或缺的工具。其中,Git是最受欢迎的版本控制系统之一。Git是由Linux的创造者Linus Torvalds在2005年创建的,用于管理Linux内核的开发。Git是一个分布式版…...

kafka面试题(基础-进阶-高阶)
目录 Kafka 基础篇 1.Kafka 的用途有哪些?使用场景如何? 2.Kafka 中的ISR、AR 又代表什么?ISR 的伸缩又指什么 3.Kafka 中的 HW、LEO、LSO、LW 等分别代表什么? 4.Kafka 中是怎么体现消息顺序性的? 5.Kafka 中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序…...

《系统架构设计师教程(第2版)》第11章-未来信息综合技术-07-大数据技术概述
文章目录 1. 大数据的定义2. 大数据的研究内容2.1 面临的问题2.2 面临的挑战2.3 分析步骤2.3.1 数据获取和记录2.3.2 信息抽取和清洗2.3.3 数据集成、聚集和表示2.3.4 查询处理、数据建模和分析2.3.5 解释 3.大数据的应用领域3.1 制造业的应用3.2 服务业的应用3.3 交通行业的应…...