ThreadLocal使用,配合拦截器HandlerInterceptor使用

2024-03-11 09:28

本文主要是介绍ThreadLocal使用,配合拦截器HandlerInterceptor使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ThreadLocal使用,配合拦截器HandlerInterceptor使用

ThreadLocal的使用场景通常涉及多线程环境下需要为每个线程保留独立状态的情况。它提供了一种简单的方式来管理线程本地变量,使得每个线程都可以独立地访问和修改自己的变量副本,而不会影响其他线程的副本。

包括的方法

ThreadLocal的主要方法包括:

  • get():获取当前线程的变量副本。
  • set(value):设置当前线程的变量副本为给定的值。
  • remove():移除当前线程的变量副本。

项目中创建

定义BaseContext类,分别设置获取当前内容、设置当前内容、移出当前内容。

public class BaseContext {public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();public static Long getCurrentId() {return threadLocal.get();}public static void setCurrentId(Long currentId) {threadLocal.set(currentId);}public static void removeCurrentId(Long id) {threadLocal.remove();}
}

需要注意的是,ThreadLocal使用完毕后应该及时调用remove()方法来清除当前线程的变量副本,以避免内存泄漏问题。另外,由于ThreadLocal使用了线程封闭的设计思想,因此在使用时应当谨慎考虑其适用性,并避免滥用。

在项目中简单使用

在发送请求时,携带id,最后在service层获取。

@RestController
@RequestMapping("/test")
@Tag(name = "测试设置ThreadLocal")
@Slf4j
public class DemoThreadLocal {@AutowiredDemoThreadLocalService demoThreadLocalService;@Operation(summary = "设置userID", description = "测试方法")@GetMapping("userId={id}")public String setUserId(@PathVariable Long id) {BaseContext.setCurrentId(id);demoThreadLocalService.demoThreadLocalUserId();return "userId";}
}

service接口。

public interface DemoThreadLocalService {void demoThreadLocalUserId();
}

service实现类中获取id。

@Service
@Slf4j
public class DemoThreadLocalServiceImpl implements DemoThreadLocalService {@Overridepublic void demoThreadLocalUserId() {// 获取当前idLong currentId = BaseContext.getCurrentId();log.info("当前id为:{}", currentId);// 使用完后移出BaseContext.removeCurrentId(currentId);}
}

在这里插入图片描述

配合拦截器使用

第一步:配置拦截器

  1. 新建interceptor包和TokenUserInterceptor类,实现HandlerInterceptor;并交给spring管理。

  2. 实现public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception方法。

  3. 我是将token放在header中的,当然也可以放在cookies中。

    • 在这里插入图片描述
  4. 判断当前token是否为空,如果为空返回false,不往下执行。

  5. 做到这步还没结束,因为这样写还不会生效。

  6. 新建config包,创建WebMvcConfiguration 并实现WebMvcConfigurationSupport

@Component
@Slf4j
public class TokenUserInterceptor implements HandlerInterceptor {public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 设置userIdString token = request.getHeader("token");System.out.println("--------------" + token + "--------------");if (token != null && !token.isEmpty()) {BaseContext.setCurrentId(Long.valueOf(token));return true;} else {return false;}}
}

第二步:配置MVC设置

匹配路径

WebMvcConfiguration内容如下。配置拦截器这样才会生效。需要拦截/test下所有请求,如图所示,拦截器识别不了通配符所以要使用addPathPatterns去匹配。

其中的方式是:protected void addInterceptors(InterceptorRegistry registry)

@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {@AutowiredTokenUserInterceptor tokenUserInterceptor;protected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(tokenUserInterceptor).addPathPatterns("/test/**");}
}

在这里插入图片描述

需要注意的是,当前只是传入一个也可以传入多个。当匹配后即可实现拦截效果,检测header中是否包含token。

在这里插入图片描述

示例,为了演示效果就随便写了下。

protected void addInterceptors(InterceptorRegistry registry) {String[] list = {};registry.addInterceptor(tokenUserInterceptor).addPathPatterns("/test/**").addPathPatterns("/test2").addPathPatterns("/test3").addPathPatterns("asa", "sas","sas").addPathPatterns(list);
}

在knif4j中测试,成功输出。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

排出路径

排出哪些路径是不需要拦截的。

protected void addInterceptors(InterceptorRegistry registry) {String[] list = {};registry.addInterceptor(tokenUserInterceptor).addPathPatterns("/test/**").excludePathPatterns("/test2").excludePathPatterns("/test3").excludePathPatterns("asa", "sas", "sas").excludePathPatterns(list);
}

在这里插入图片描述

第三步:Controller层中

controller层,在路径中不传入id,通过拦截器获取header中token。这一层并不需要做什么,只是为了写一个接口让MVC拦截。

@RestController
@RequestMapping("/test")
@Tag(name = "测试设置ThreadLocal")
@Slf4j
public class DemoThreadLocal {@AutowiredDemoThreadLocalService demoThreadLocalService;@Operation(summary = "拦截器中设置UserId", description = "测试方法")@GetMapping("userId")public String userId() {demoThreadLocalService.demoThreadLocalUserId();return "userId";}
}

第四步:查看内容

service和上面一样。

@Service
@Slf4j
public class DemoThreadLocalServiceImpl implements DemoThreadLocalService {@Overridepublic void demoThreadLocalUserId() {// 获取当前idLong currentId = BaseContext.getCurrentId();log.info("当前id为:{}", currentId);// 使用完后移出BaseContext.removeCurrentId(currentId);}
}
emoThreadLocalUserId() {// 获取当前idLong currentId = BaseContext.getCurrentId();log.info("当前id为:{}", currentId);// 使用完后移出BaseContext.removeCurrentId(currentId);}
}

这篇关于ThreadLocal使用,配合拦截器HandlerInterceptor使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/797399

相关文章

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

Python虚拟环境终极(含PyCharm的使用教程)

《Python虚拟环境终极(含PyCharm的使用教程)》:本文主要介绍Python虚拟环境终极(含PyCharm的使用教程),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录一、为什么需要虚拟环境?二、虚拟环境创建方式对比三、命令行创建虚拟环境(venv)3.1 基础命令3

Python Transformer 库安装配置及使用方法

《PythonTransformer库安装配置及使用方法》HuggingFaceTransformers是自然语言处理(NLP)领域最流行的开源库之一,支持基于Transformer架构的预训练模... 目录python 中的 Transformer 库及使用方法一、库的概述二、安装与配置三、基础使用:Pi

关于pandas的read_csv方法使用解读

《关于pandas的read_csv方法使用解读》:本文主要介绍关于pandas的read_csv方法使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录pandas的read_csv方法解读read_csv中的参数基本参数通用解析参数空值处理相关参数时间处理相关

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

SpringBoot条件注解核心作用与使用场景详解

《SpringBoot条件注解核心作用与使用场景详解》SpringBoot的条件注解为开发者提供了强大的动态配置能力,理解其原理和适用场景是构建灵活、可扩展应用的关键,本文将系统梳理所有常用的条件注... 目录引言一、条件注解的核心机制二、SpringBoot内置条件注解详解1、@ConditionalOn

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求