ThreadLocal的使用

news2024/11/25 15:25:13

ThreadLocal 一般不会单独使用,基本上都是 放在一个工具类中,然后在拦截器中去使用(至少存储 Token 的时候是这样的)

这里为了更加还原真实的线上环境,直接就用了 拦截器+统一返回+全局异常捕获+ThreadLocal,项目还是比较完整的

首先创建一个项目 启动后看项目是否能跑通 这个就很简单了,直接略过

创建 ThreadlLocal 的工具类

public class TokenUtils {
    // 通过 ThreadLocal 存储 token
    private static final ThreadLocal<String> tokenThreadLocal = new ThreadLocal<>();

    // 设置 token
    public static void setToken(String token) {
        tokenThreadLocal.set(token);
    }

    // 获取 token
    public static String getToken() {
        return tokenThreadLocal.get();
    }

    // 清除 token
    public static void clearToken() {
        tokenThreadLocal.remove();
    }
}

编写拦截器 并注册到 容器中

//一个拦截器,拦截请求,把请求的时间记录下来,并将请求头中的 token 拿出来
public class MyInterceptor implements HandlerInterceptor {

    @Override//在请求处理之前进行调用(Controller方法调用之前)
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //记录请求时间
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        //将请求头中的 token 拿出来
//        String token = request.getHeader("token");
        //从 Authorization 中获取 token 并去除 Bearer 字符串
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
        }

        //将 token 放入 ThreadLocal 中
        TokenUtils.setToken(token);
        return true;
    }

    @Override//请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //获取请求时间
        long startTime = (long) request.getAttribute("startTime");
        //计算请求处理时间
        long endTime = System.currentTimeMillis();
        System.out.println("本次请求处理时间为:" + (endTime - startTime) + "ms");
    }

    @Override//在整个请求结束之后被调用,也就是在 DispatcherServlet 渲染了对应的视图之后执行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //移除 ThreadLocal 中的 token
        System.out.println("清除 token" );
        TokenUtils.clearToken();
    }
}

注意,HandlerInterceptor 并不能让你 对返回值进行一些处理和修改,如果你想对返回值做处理和修改,你需要去了解的是 ResponseBodyAdvice

@Configuration
public class MyWebConfig implements WebMvcConfigurer {

    //注册 MyInterceptor 拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**")
                .excludePathPatterns("/public/**"); // 排除"/public"下的所有请求
    }
}

创建一个类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyStudent
{
    private String name;
    private int age;
}

统一的返回值

@Data
// 统一返回类
public class UnifiedReturn<T> {

    private int code;// 状态码  200正常  各种异常 需要在 枚举里面定义
    private String msg;// 返回信息
    private T data;// 返回数据

    public UnifiedReturn(T data) {
        this.data = data;
    }

    //success
    public static <T> UnifiedReturn<T> success(T data) {
        UnifiedReturn<T> aReturn = new UnifiedReturn<>(data);
        aReturn.setCode(UnifiedReturnEnum.SUCCESS.getCode());
        aReturn.setMsg(UnifiedReturnEnum.SUCCESS.getMsg());
        return aReturn;
    }

    //error
    public static <T> UnifiedReturn<T> error(int code, String msg) {
        UnifiedReturn<T> aReturn = new UnifiedReturn<>(null);
        aReturn.setCode(code);
        aReturn.setMsg(msg);
        return aReturn;
    }
}

返回值的枚举

// 统一返回 枚举
public enum UnifiedReturnEnum {

    SUCCESS(200, "成功"),
    FAIL(500, "失败"),
    NO_PERMISSION(403, "无权限"),
    NOT_FOUND(404, "未找到"),
    PARAM_ERROR(400, "参数错误");

    private int code;
    private String msg;

    UnifiedReturnEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

统一的 异常捕获

@ControllerAdvice//全局异常处理
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseBody  //返回json  这边是一定要加的
    public UnifiedReturn<String> exceptionHandler(Exception e) {
        return UnifiedReturn.error(UnifiedReturnEnum.FAIL.getCode(), e.getMessage());
    }
}

控制器

@RestController
@RequestMapping("/basic")
public class BasicController {

    @GetMapping("/hello")
    public UnifiedReturn<MyStudent> hello() {
        String token = TokenUtils.getToken();//该方法想在哪里用都可以,只要在同一个线程中 都能获取到 token
        System.out.println("token: " + token);
        return UnifiedReturn.success(new MyStudent("theonefx", 18));
    }

    //测试异常处理--这里测试的是 运行时异常
    @GetMapping("/exception")
    public UnifiedReturn<String> exception() {
       int i = 1/0;
       return UnifiedReturn.success("success");//不会执行到这里
    }

    @GetMapping("/exception2")//这里测试的是 主动抛出的异常
    public UnifiedReturn<String> test() {
       throw new RuntimeException("test exception");
    }

}

请求看一下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

生信算法8 - HGVS转换与氨基酸字母表

HGVS 概念 HGVS 人类基因组变异协会(Human Genome Variation Society)提出的转录本编号&#xff0c;cDNA 参考序列(以前缀“c.”表示)、氨基酸参考序列(以前缀“p.”表示)。cDNA 中一种碱基被另一种碱基取代&#xff0c;以“>”进行表示&#xff0c;如&#xff1a;c.2186A&…

软件测试之解构单元测试

软件单元测试是对软件中的最小可测试单元进行检查和验证的过程。这些单元可以是函数、方法、类实例&#xff0c;或者是任何具有明确功能、规格定义和接口定义的程序代码模块。单元测试是软件开发过程中的最低级别的测试活动&#xff0c;它确保软件的独立单元在与程序的其他部分…

Jar打包成Service在Window运行

直接启动 bat脚本直接启动jar包 Spring Boot 部署在Windows Service启动 环境 电脑环境需要安装Microsoft.NETFramework 4 Microsoft.NETFramework 4 打包 WinSW 下载exe和xml配置文件&#xff0c;将exe和xml放在同一个目录下&#xff0c;并且重命名为一样的名字&…

Ideogram-免费使用的 AI 工具,可以生成逼真的图像、海报、徽标

工具来源:Ideogram | AI工具箱 什么是Ideogram AI? Ideogram AI是一款高效的工具,旨在将文本与AI生成的图像结合在一起。该应用程序提供了用户友好的界面,使您能够轻松地制作出色的艺术作品、标志和设计。 与传统工具不同,Ideogram AI因其能够以无与伦比的简便和速度将…

Git 查看当前分支是基于哪个分支拉取(源头分支)

场景&#xff1a; 项目中使用 Git 管理代码仓库的时候&#xff0c;随着项目的持续迭代及项目的扩展&#xff0c;多版本并行开发是非常常见的事情&#xff0c;多版本并行开发就伴随着多分支&#xff0c;随着 Git 的分支越拉越多&#xff0c;这时候很容易造成分支的混乱&#xf…

webgis 之 地图投影

地图投影 什么是地图投影目的种类等角投影的分类墨卡托投影Web 墨卡托投影 参考小结 为了更好地展示地球上的数据&#xff0c;需要将地球投影到一个平面上。地图投影是一个数学问题&#xff0c;按照一定的几何关系&#xff0c;将地球上的经纬度坐标映射到一个平面上的坐标。地球…

由 Vault 支持的 KES 的 MinIO Operator

为了提供安全锁定和擦除的合规性功能&#xff0c;MinIO 使用服务器端加密 &#xff08;SSE&#xff09; 在存储层加密对象&#xff0c;以保护对象作为写入操作的一部分。MinIO 以极高的效率做到这一点——基准测试表明 MinIO 能够以接近线速进行加密/解密。 MinIO 使用的秘诀是…

【头歌】HBase扫描与过滤答案 解除复制粘贴限制

解除复制粘贴限制 当作者遇到这个限制的时候火气起来了三分&#xff0c;然后去网上搜索答案&#xff0c;然后发现了一位【碳烤小肥肠】居然不贴代码&#xff0c;XX链接&#xff0c;贴截图&#xff0c;瞬时火气冲顶&#xff0c;怒写此文 首先启动万能的控制台&#xff0c;然后C…

帕金森综合征的预防方法

帕金森综合征是一种慢性神经退行性疾病&#xff0c;目前尚无法彻底治愈。然而&#xff0c;通过采取一些预防措施&#xff0c;可以降低患病风险或延缓病情发展。以下是一些基于最新研究和医学建议的预防方法&#xff1a; 健康饮食&#xff1a;保持低盐、低脂饮食&#xff0c;多吃…

SQL新手蜕变:掌握这20条常用SQL语句,让你也能成为高手!

序言 在现代软件开发中&#xff0c;SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;作为与数据库交互的标准编程语言&#xff0c;是每个开发者必学的基础技能。掌握SQL并在数据库管理与数据分析中应用自如&#xff0c;能显著提升开发效率和数…

语音相关算法学习整理

最近看了一下百度paddlespeech的一些公开课&#xff0c;把课程里的视频内容大体听了一下&#xff0c;现在整理一下笔记。教程链接见&#xff1a;飞桨AI Studio星河社区-人工智能学习与实训社区 语音识别的过程可以这样简单概括&#xff1a; 将声音信号经过预加重、加窗、fft等…

蓝牙数传芯片TD5325A,蓝牙5.1—拓达半导体

拓达TD5325A芯片是一款支持蓝牙BLE&SPP的纯数传芯片&#xff0c;蓝牙5.1版本。芯片的亮点在于性能强&#xff0c;支持APP端直接对芯片做设置与查询操作&#xff0c;包括修改蓝牙名、UUID、MAC地址&#xff0c;以及直接操作蓝牙芯片自身的IO与PWM口&#xff0c;还包括支持简…

开发产品要遵循这些「关键规则」

目录 简介 关键规则 第一点&#xff1a;了解产品的操作使用环境 第二点&#xff1a;尽可能计划将来的功能 第三点&#xff1a;静电 ESD 保护 第四点&#xff1a;尽早考虑 BOM 成本 第五点&#xff1a;开发文件管理&#xff08;原理图、BOM、代码等&#xff09; 产品资源…

如何使用Excel与Outlook实现邮件群发:详细教程

引言 在工作中&#xff0c;我们经常需要发送大量邮件。手动发送既费时又容易出错。本教程将教你如何使用Excel和Outlook&#xff0c;通过简单的VBA代码实现邮件的自动群发&#xff0c;提高工作效率。 准备工作 在开始之前&#xff0c;你需要确保以下工具已经安装在电脑上&am…

1969python房屋租赁管理系统mysql数据库Flask结构BootStrap布局计算机软件工程网页

一、源码特点 python Flask房屋租赁管理系统是一套完善的web设计系统mysql数据库 &#xff0c;对理解python编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 python flask 房屋租赁管理系统 开发环境pycharm mysql …

1958springboot VUE宿舍管理系统开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot VUE宿舍管理系统是一套完善的完整信息管理类型系统&#xff0c;结合springboot框架和VUE完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09; &#xff0c;系统具有完整的源代码和数…

QML 列表,图片展示(一)

文章目录 1.QML 列表&#xff0c;图片展示效果图2.项目基本说明3.项目详解3.1界面显示部分3.2 网络部分 4.源代码5.flickr图片查询链接&#xff0c;后面我们将调整代码&#xff0c;获取更多图片 1.QML 列表&#xff0c;图片展示效果图 2.项目基本说明 该项目来自Qt示例程序 Ph…

目前哪个充电宝品牌比较好?四款优质充电宝分享

在电量成为现代生活不可或缺的生产资源的时代&#xff0c;选择一款优质的充电宝无疑是保证移动设备持续运作的关键。面对市场上众多品牌和型号的充电宝&#xff0c;消费者在选择时可能会感到困惑和迷茫。本文将为您揭示哪些品牌真正代表了耐用性和质量的典范&#xff0c;让自己…

使用 LangServe 构建和部署 MinIO 支持的 LangChain Agent API

我们在LangChain的创新世界中的旅程揭示了其在转变数据管理和应用程序功能方面的强大能力。 通过之前的讨论&#xff0c;我们深入探讨了几个主题&#xff0c;同时探索了LangChain的复杂功能。在本文中&#xff0c;我们将以“使用 MinIO 赋能 Langchain 代理”中涵盖的概念为基…

数学建模系列(4/4):Matlab建模实战

目录 引言 1. Matlab简介与安装 1.1 Matlab简介 1.2 Matlab的安装 2. Matlab基础操作 2.1 Matlab基础语法和常用命令 2.2 Matlab中的数据类型和数据结构 3. 用Matlab进行建模 3.1 矩阵运算与线性代数 矩阵运算 3.2 Matlab中的绘图功能 绘制2D图形 绘制3D图形 3.3…