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、管理员: 用户管理、用户管理、栏目管理、网…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...