SpringBoot拦截器获取token用户对象优雅地传递到Controller层
项目场景:
SpringBoot拦截器获取token用户对象优雅地传递到Controller层
问题描述
后端有许多接口都需要请求中携带有正确的Token,这时采用拦截器来验证token,但是每个接口都还是需要解析一遍token,浪费资源,不免显得代码繁琐,臃肿。
解决方案:
我们可以把用户信息存储起来,方便其它地方获取,两种方式:
- 使用ThreadLocal线程存储(推荐)
- 存储到上下文中request.setAttribute
1、自定义拦截器Interceptor
抛出的异常需要自己捕捉,返回
package com.test.aop;import com.test.entity.TokenUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** Token拦截器*/
@Component
@Slf4j
public class TokenInterceptor implements HandlerInterceptor {/*** 存储用户信息*/private static ThreadLocal<TokenUserInfo> userThread = new ThreadLocal<>();@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 从header中获取tokenString token = request.getHeader(CommonConstant.ACCESS_TOKEN);// 如果参数中不存在token,则报错if (StringUtils.isBlank(token)) {throw new RuntimeException("请求头缺少token参数");}try {// TODO 根据token获取用户信息// ......}catch (Exception e){log.error("获取用户信息失败:", e);throw new RuntimeException("获取用户信息失败");}//模拟已经获取到了用户信息TokenUserInfo tokenUserInfo = new TokenUserInfo();tokenUserInfo.setUserId("1227086153ef415896da5819d4fb4c2f");tokenUserInfo.setLoginAccount("test");tokenUserInfo.setLoginUserName("测试");//token失效if(tokenUserInfo == null){throw new RuntimeException("token失效");}/** 存储用户信息方便其它地方获取,两种方式* 1.使用ThreadLocal线程存储(推荐)* 2.存储到上下文中request.setAttribute*/// 放入线程域userThread.set(tokenUserInfo);//2.存储到上下文中request.setAttribute
// request.setAttribute("tokenUserInfo",tokenUserInfo);//放行return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//程序运行结束之后,删除线程,防止内存泄漏userThread.remove();}public static TokenUserInfo getUser() {return userThread.get();}}
用户实体类
package com.test.entity;import lombok.Data;/*** 用户信息**/
@Data
public class TokenUserInfo {/*** 用户id*/private String userId;/*** 登录帐号*/private String loginAccount;/*** 用户名*/private String loginUserName;
}
2、配置拦截器
package com.test.config;import com.test.aop.TokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;/*** WebMvc配置*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {/*** 解决跨域问题*/@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS").maxAge(3600);}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");registry.addResourceHandler("/swagger/**").addResourceLocations("classpath:/static/swagger/");registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");}@Resourceprivate TokenInterceptor tokenInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//不拦截的地址List<String> excludedList = new ArrayList<>();//swagger地址excludedList.add("/swagger-ui.html");excludedList.add("/swagger-ui.html/**");excludedList.add("/webjars/**");excludedList.add("/swagger/**");excludedList.add("/doc.html");excludedList.add("/doc.html/**");excludedList.add("/swagger-resources/**");excludedList.add("/v2/**");excludedList.add("/favicon.ico");registry.addInterceptor(tokenInterceptor).addPathPatterns("/**")//拦截所有请求.excludePathPatterns(excludedList);//排除的请求super.addInterceptors(registry);}
}
3、Controller层获取
package com.test.controller;import com.test.aop.TokenInterceptor;
import com.test.entity.TokenUserInfo;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;@RestController
@Api(tags = "测试接口")
@RequestMapping("/test")
public class TestController {@RequestMapping(value = "/get", method = RequestMethod.GET)public String get(HttpServletRequest request) {/** 优雅的获取用户信息,两种方式* 1.使用ThreadLocal线程存储(推荐)* 2.存储到上下文中request.setAttribute*/TokenUserInfo tokenUserInfo = TokenInterceptor.getUser();
// TokenUserInfo tokenUserInfo = (TokenUserInfo) request.getAttribute(CommonConstant.USER_INFO);return "success";}
}
参考源码:https://download.csdn.net/download/u011974797/85849196
相关文章:
SpringBoot拦截器获取token用户对象优雅地传递到Controller层
项目场景: SpringBoot拦截器获取token用户对象优雅地传递到Controller层 问题描述 后端有许多接口都需要请求中携带有正确的Token,这时采用拦截器来验证token,但是每个接口都还是需要解析一遍token,浪费资源,不免显得…...
从零开始学HCIA之SDN03
1、VXLAN相关概念 (1)NVE(Network Virtual Edge),网络虚拟化边界,是运行VXLAN的设备,其实体是一种虚拟逻辑接口,负责VXLAN数据的封装和解封装,其主要参数包括源VTEP以及…...
C语言深度理解之——结构体内存对齐
前言: 在C语言中,结构体(struct)是一种用户自定义的数据类型,可以包含不同类型的数据成员。在定义结构体时,编译器会根据平台的要求对结构体的内存进行对齐,以提高内存访问的效率。结构体内存对…...
LeetCode 热题 100 | 回溯(二)
目录 1 39. 组合总和 2 22. 括号生成 3 79. 单词搜索 菜鸟做题,语言是 C,感冒快好版 关于对回溯算法的理解请参照我的上一篇博客; 在之后的博客中,我将只分析回溯算法中的 for 循环。 1 39. 组合总和 题眼:c…...
混合内容错误https中加载了http
一、遇到问题 iframe嵌套时,混合内容错误https中加载了http,但是已经确认了ifreme中是https的,最后发现在/my/edit?applyid1改为/my/edit/?applyid1,加了一个斜杠,直接解决了 /my/edit是vue页面,其他页…...
游戏免费下载平台模板源码
功能介绍 此游戏网站模板源码是专门为游戏下载站而设计的,旨在为网站开发者提供一个高效、易于维护和扩展的解决方案。 特点: 响应式设计:我们的模板可以自适应不同设备屏幕大小,从而为不同平台的用户提供最佳的浏览体验。 …...
鸿蒙视频播放的实现
文章目录 前言播放效果视频播放的实现总结 一、前言 现在市面上很多应用都跟视频有关,那么在鸿蒙系统上怎么来播放视频呢,今天就讲解视频播放控件,让你也能快速地进行视频播放功能开发。 最后呢,我会提供一个鸿蒙中涉及的主要…...
QT----计算器
目录 1 搭建标准界面2、 逻辑编写2.1 初始化 github链接:基于qt的计算器 更多内容可以点击这里查看个人博客:个人博客 1 搭建标准界面 按照下图搭设界面 修改样式让这计算器看起来更像一点,同时对按钮分组进行样式编辑,添加字符…...
Linux:kubernetes(k8s)Deployment的操作(13)
创建deployment 命令 kubectl create deploy nginx-deploy --imagenginx:1.7.9 再去使用以下命令分别查询 ubectl get deploy kubectl get replicaset kubectl get pod 他是一个层层嵌套的一个关系 首先是创建了一个 deploy 里面包含着replicaset replicaset里面含有…...
20240619-James-快速鸟瞰并发编程, 呕心沥血整理的架构技术(第3篇)
接着第1, 2篇后,我们继续来跟进一下并发编程的其它内容,如下: 第9节 java.util.concurrent包 线程池 线程池的核心接口是ExecutorService。java.util.concurrent还提供了一个静态工厂类Executors,其中包含用于创建配置线程池的…...
C语言——详解字符函数和字符串函数(一)
Hi,铁子们好呀!今天博主来给大家更一篇C语言的字符函数和字符串函数~ 具体讲的内容如下: 文章目录 🎆1.字符分类函数💯💯⏩1.1 什么是字符分类函数的?💯💯⏩1.2 字符函数的类型有哪…...
三款内衣洗衣机的顶级较量:希亦、小吉、由利,谁才是性价比之王?
洗衣机在我们的生活中可谓是非常常见的了,几乎每家每户都具备着一台。即便是有洗衣机,也有不少人不会将自己我贴身衣物直接扔在洗衣机里清洗,而是会自己手工手洗。这跟我们传统上的观念有很大的关系,认为把内衣、内裤等贴身衣物放…...
Java枚举多值映射应用
在日常系统交互中,经常遇到两个系统间定义的枚举不一致,在接口调用时需要转换,记录实现,方便备查。 场景 双方的支付方式定义不同,一侧为数字,一侧为英文,若使用 if 判断,则显得繁琐…...
css--浮动
一. 浮动的简介 在最初,浮动是用来实现文字环绕图片效果的,现在浮动是主流的页面布局方式之一。 二. 元素浮动后的特点 🤢脱离文档流。😊不管浮动前是什么元素,浮动后:默认宽与高都是被内容撑开࿰…...
基于有限状态机开发健壮的Nodejs/TCP客户端
有限状态机是一种数学计算模型,它描述了在任何给定时间只能处于一种状态的系统的行为。形式上,有限状态机有五个部分: 初始状态值 (initial state)有限的一组状态 (states)有限的一组事件 (events)由事件驱动的一组状态转移关系 (transition…...
javaEE13(网站第8章两个课后题)
1、对“jspservletjavabean实现分页查询”功能做如下补充: (1)记录批量删除:每个记录前添加复选框,点击批量删除,删除选中记录。 增加跳转到任意页功能。用户可改变每页记录条数。 页面&am…...
【Leetcode每日一题】 递归 - 反转链表(难度⭐)(35)
1. 题目解析 题目链接:206. 反转链表 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 一、递归函数的核心任务 递归函数的主要职责是接受一个链表的头指针,并返回该链表逆序后的新头结点。递归…...
Unity基础学习
目录 基础知识点3D数学——基础Mathf三角函数坐标系 3D数学——向量向量模长和单位向量向量的加减乘除向量点乘向量叉乘向量插值运算 3D数学——四元数为何使用四元数四元数是什么四元数常用方法四元数计算 MonoBehavior中的重要内容延迟函数协同程序协同程序原理 Resources资源…...
Java并发编程学习笔记:AQS
Java并发编程学习笔记:AQS 一、底层原理核心功能同步状态管理CLH 队列和线程调度机制独占模式与共享模式模板方法设计模式自旋、阻塞与超时机制 运行流程 二、锁的公平性公平锁非公平锁 三、容器实现 JUC中的AQS(AbstractQueuedSynchronizer)…...
Github上哪些好用的工具
专注于web漏洞挖掘、内网渗透、免杀和代码审计,感谢各位师傅的关注!网安之路漫长,与君共勉! Qexo-爱写博客的师傅强烈推荐 漂亮的 Hexo 静态博客编辑器。该项目是基于 Django 的 Hexo 静态博客管理后台,支持文章管理、…...
在多模型间切换使用时对响应速度与一致性的感受
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 在多模型间切换使用时对响应速度与一致性的感受 作为一名需要频繁调用大模型API的开发者,我的日常工作离不开与各类模型…...
2022年AI工程实战指南:从H100到Chinchilla的十大关键技术落地
1. 这不是一份“新闻简报”,而是一份2022年4月AI技术演进的实操解剖报告 如果你在2022年春天打开过任何一家AI实验室的内部通讯、技术周会纪要,或者翻过几篇刚上线的arXiv论文,你大概率会看到一连串让人头皮发麻的名词:H100、PaLM…...
物理学巅峰成就巡礼:从牛顿到量子,探索宇宙与微观世界的革命性突破
1. 项目概述:一次对物理学巅峰成就的巡礼2019年,诺贝尔物理学奖授予了三位天体物理学家——詹姆斯皮布尔斯、米歇尔马约尔和迪迪埃奎洛兹,以表彰他们在物理宇宙学理论以及系外行星发现领域的开创性贡献。这个奖项像一束聚光灯,将公…...
CTF 竞赛干货|50 个实战解题思路,收藏一篇就够用
CTF选手必藏的50个实战解题思路!一篇够用! CTF竞赛的核心逻辑 • 核心目标:快速拆解问题(Flag导向)、工具链协作、模式化思维。• 关键原则:先广度后深度(优先收集信息)、分治策略&…...
DALL·E Mini实战指南:轻量级文本生成图像的平民化落地
1. 项目概述:这不是“另一个AI画图工具”,而是一次轻量级生成式AI的平民化实践Dalle Mini Is Amazing — And You Can Use It! 这句话乍看像社交媒体上随手转发的惊叹,但拆开来看,它其实精准锚定了三个关键信息点:Dall…...
深度神经网络非线性行为的分段几何诊断法
1. 这不是又一篇“调库跑通”的深度学习教程——它直指模型失效的根源你有没有遇到过这样的情况:数据质量没问题,网络结构参考了SOTA论文,超参也做了网格搜索,但模型在验证集上就是卡在某个精度上再也上不去?损失曲线看…...
接口测试入门:从Postman到Python自动化实战指南
1. 别再被“接口测试”四个字吓退——它其实比你想象中更像点外卖很多人第一次听说“接口测试”,脑子里立刻浮现出一串密密麻麻的HTTP请求、满屏curl命令、Postman里层层嵌套的JSON Body,还有动不动就报错的401、500、404……然后默默关掉网页࿰…...
SQLines数据库迁移工具:从零开始的完整使用指南
SQLines数据库迁移工具:从零开始的完整使用指南 【免费下载链接】sqlines SQLines Open Source Database Migration Tools 项目地址: https://gitcode.com/gh_mirrors/sq/sqlines SQLines是一款功能强大的开源数据库迁移工具,专门用于在不同数据库…...
5分钟掌握Excel MCP Server:无需安装Excel的终极数据处理方案
5分钟掌握Excel MCP Server:无需安装Excel的终极数据处理方案 【免费下载链接】excel-mcp-server A Model Context Protocol server for Excel file manipulation 项目地址: https://gitcode.com/gh_mirrors/ex/excel-mcp-server 在数据驱动的现代工作中&…...
Python:4 == 4.0 结果为True的原因
特殊情况:在 Python 中,整数和浮点数进行比较时,如果数值相等,则结果为 True。即 4 4.0 的结果是 True。如果两个对象代表相同的概念或数值,即使类型不同(如 int 和 float),也可能返…...
