【Java21】在spring boot中使用ScopedValue

文章目录

  • 0.环境说明
  • 1.基础知识
    • 1.1 ScopedValue的特点
  • 2.应用场景
    • 2.1 spring web项目中,使用ScopedValue传递上下文(全局不可变量)
    • 2.2 spring grpc项目中,使用ScopedValue传递上下文(全局不可变量)
  • 3.ScopedValue的优势

0.环境说明

spring boot:3.3.3
jdk:OpenJDK 21.0.5
项目构建工具:maven

本文所涉及到的代码均已上传:https://github.com/TreeOfWorld/java21-demo/

1.基础知识

1.1 ScopedValue的特点

  • 值是不可变的(所以和record是绝配)
  • 需要定义作用域,并且只能在自己的作用域中生效
  • 值可以被嵌套覆盖

2.应用场景

2.1 spring web项目中,使用ScopedValue传递上下文(全局不可变量)

用于在虚拟线程的项目中取代Thread Value

  1. 开启预览功能的编译

    ScopeValue在java21中还是预览功能,所以在编译时需要添加参数--enable-preview,对于maven工程,就是在pom.xml文件中增加如下配置:

    	<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.11.0</version> <!-- 确保使用最新版本 --><configuration><release>21</release> <!-- 设置为你的 Java 版本 --><compilerArgs><arg>--enable-preview</arg> <!-- 启用预览功能 --></compilerArgs></configuration></plugin></plugins></build>
    
  2. 创建一个spring web工程(这步没什么好说的)

  3. 通过spring的http filter,将请求中的header中的信息保存到上下文中

    1. 创建一个上下文UserContext类
      public class UserContext {public record UserInfo(String username, String password) {}private static final ScopedValue<UserInfo> userInfo = ScopedValue.newInstance();public static ScopedValue<UserInfo> getContext() {return userInfo;}}
      
    2. 创建一个http过滤器,在收到请求后,将header中的username和password存到刚刚的UserContext上下文中
      @Slf4j
      @Component
      public class UserInfoFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String username = request.getHeader(HttpConstant.USERNAME);String password = request.getHeader(HttpConstant.PASSWORD);log.info("username:{}, password:{}", username, password);ScopedValue<UserContext.UserInfo> userInfoContext = UserContext.getContext();// 为当前线程(也可以是虚拟线程)绑定UserContext的值// 为UserContext定义ScopedValue的作用域为filterChain.doFilter(request, response);ScopedValue.where(userInfoContext, new UserContext.UserInfo(username, password)).run(() -> {try {filterChain.doFilter(request, response);} catch (IOException | ServletException e) {throw new RuntimeException(e);}});}
      }
      
    3. 定义一组controller、service、serviceImpl用于在上下文中读取UserContext
      // 控制器
      @Slf4j
      @RestController
      public class UserInfoController {final UserInfoService userInfoService;UserInfoController(UserInfoService userInfoService) {this.userInfoService = userInfoService;}@GetMapping("/user-info")public UserContext.UserInfo getUserInfo() {log.info("getUserInfo in controller: {}", UserContext.getContext().get());return this.userInfoService.getUserInfo();}}// 接口类
      public interface UserInfoService {UserContext.UserInfo getUserInfo();
      }// 实现类
      @Slf4j
      @Service
      public class UserInfoServiceImpl implements UserInfoService {@Overridepublic UserContext.UserInfo getUserInfo() {log.info("getUserInfo in service: {}", UserContext.getContext().get());return UserContext.getContext().get();}
      }
      
    4. 启动服务,并调用接口验证ScopedValue是否生效
      curl --request GET \--url http://localhost:8080/user-info \--header 'password: this is a password' \--header 'username: this is a username'
      
      可以看到服务中会打印如下日志,可以看到,filter中读取到了header中的username和password,而在controller和service中都读取到了UserContext的信息
      2025-07-03T00:01:27.121+08:00  INFO 23588 --- [nio-8080-exec-3] c.treeofworld.elf.filter.UserInfoFilter  : username:this is a username, password:this is a password
      2025-07-03T00:01:27.123+08:00  INFO 23588 --- [nio-8080-exec-3] c.t.elf.controller.UserInfoController    : getUserInfo in controller: UserInfo[username=this is a username, password=this is a password]
      2025-07-03T00:01:27.123+08:00  INFO 23588 --- [nio-8080-exec-3] c.t.elf.service.UserInfoServiceImpl      : getUserInfo in service: UserInfo[username=this is a username, password=this is a password]
      
      启用虚拟线程的话,效果也是一样的
      2025-07-03T00:05:53.074+08:00  INFO 48100 --- [omcat-handler-0] c.treeofworld.elf.filter.UserInfoFilter  : username:this is a username, password:this is a password
      2025-07-03T00:05:53.108+08:00  INFO 48100 --- [omcat-handler-0] c.t.elf.controller.UserInfoController    : getUserInfo in controller: UserInfo[username=this is a username, password=this is a password]
      2025-07-03T00:05:53.109+08:00  INFO 48100 --- [omcat-handler-0] c.t.elf.service.UserInfoServiceImpl      : getUserInfo in service: UserInfo[username=this is a username, password=this is a password]
      
  4. 总结
    在这里,我们通过spring boot的http filter,将header中的两个字段通过一个记录类(record)维护到了整个请求的上下文中。

  5. 思考

    • 如果在业务处理过程中,UserContext的值就是需要发生变更该怎么办?

2.2 spring grpc项目中,使用ScopedValue传递上下文(全局不可变量)

对于spring grpc来说,就不再是对filter操作了,而是在grpc拦截器interceptor中进行操作

  1. 开启预览功能的编译
  2. 创建两个spring grpc工程,一个grpc client,一个grpc server
  3. 编写GrpcServerInterceptor和GrpcClientInterceptor

3.ScopedValue的优势

  • 配合虚拟线程使用,减少内存开销

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

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

相关文章

第10篇 图像语义分割和目标检测介绍

语义分割(Semantic Segmentation)是图像处理和机器视觉一个重要分支&#xff0c;其目标是精确理解图像场景与内容。语义分割是在像素级别上的分类&#xff0c;属于同一类的像素都要被归为一类&#xff0c;因此语义分割是从像素级别来理解图像的。如下如所示的照片&#xff0c;属…

微算法科技(NASDAQ MLGO)基于量子图像处理的边缘检测算法:开拓图像分析新视野

在当今数字化时代&#xff0c;图像数据海量增长&#xff0c;边缘检测作为图像处理的关键环节&#xff0c;在机器视觉、医学成像、安防监控等众多领域有着至关重要的作用。传统边缘检测算法在处理复杂图像时&#xff0c;面临计算效率低、精度不足等问题。量子计算的兴起&#xf…

SM4密码算法的C语言实现(带测试)

一、SM4算法原理 SM4是中国国家密码管理局于2012年发布的国家商用密码算法标准&#xff0c;也称为GB/T 32907-2016。它是一种分组对称加密算法&#xff0c;采用32轮非线性迭代结构&#xff0c;分组长度和密钥长度均为128位。SM4算法的设计充分考虑了安全性、高效性和实现简便性…

【React Native原生项目不能运行npx react-native run-android项目】

运行命令报错,帮我修复X:\jetbrains-workspace\theme-wallpaper>npx react-native run-android error Android project not found. Are you sure this is a React Native project? If your Android files are located in a non-standard location (e.g. not inside ‘andro…

SPLADE 在稀疏向量搜索中的原理与应用详解

今天看到Sentence Transformers v5.0 集成了许多稀疏嵌入模型。为了搞清楚什么稀疏嵌入模型以及应用&#xff0c;查到了SPLADE&#xff0c;比较巧合的是在paper reading分享的时候看到有同学分享了一片ACL 2025的工作也是基于SPLADE去做的。下面结合一些资料分享关于SPLADE 在稀…

wpf的Binding之UpdateSourceTrigger

前言 在wpf界面开发中&#xff0c;Binding的源和目标之间可以通过Mode来决定数据的传递方向&#xff0c;同时数据传递时的触发条件也是可以有多种情况&#xff0c;多种情况由UpdateSourceTrigger属性来控制&#xff0c;该属性有Default、Explicit、LostFocus、PropertyChanged…

突破性进展:超短等离子体脉冲实现单电子量子干涉,为飞行量子比特奠定基础

关键词&#xff1a;量子计算、电子干涉测量、等离子体脉冲、马赫-曾德尔干涉仪、非绝热量子操控 研究背景 在量子计算领域&#xff0c;飞行量子比特&#xff08;flying qubits&#xff09;因其动态传播特性和通过库仑相互作用直接纠缠的能力&#xff0c;成为替代光子量子比特的…

Java调用百度地图天气查询服务获取当前和未来天气-以贵州省榕江县为例

目录 前言 一、百度天气查询服务 1、天气查询服务 2、查询API简介 二、UniHttp集成天气查询服务 1、定义访问接口 2、业务集成调用 三、天气检索成果 1、IDE检索结果输出 2、互联网天气对比 四、总结 前言 天气与人们的生活息息相关&#xff0c;无论是日常出行、农业…

Windows Excel文档办公工作数据整理小工具

在现代办公环境中&#xff0c;Excel 是处理数据不可或缺的工具&#xff0c;而 “Excel 工作圈小工具” 则如同为 Excel 量软件下载地址安装包 身打造的超级增效器&#xff0c;它是一个集合了大量 Excel 功能的绿色工具软件&#xff0c;能够显著提升你的工作效率。 这款软件虽然…

Node.js v22.5+ 官方 SQLite 模块全解析:从入门到实战

在 Node.js v22.5.0 及更高版本中&#xff0c;node:sqlite 模块作为内置模块被引入&#xff0c;为开发者提供了与 SQLite 数据库交互的官方支持。以下是关于 node:sqlite 模块的详细介绍&#xff1a; 一、模块启用与导入 启用方式&#xff1a;node:sqlite 模块目前处于活跃开…

API接口安全-2:签名、时间戳与Token如何联手抵御攻击

在API接口通信中&#xff0c;数据传输的安全性至关重要。无论是前端与后端的交互&#xff0c;还是企业间的接口对接&#xff0c;一旦缺乏有效的安全校验&#xff0c;攻击者可能通过抓包篡改参数&#xff08;如修改订单金额&#xff09;、重放攻击&#xff08;重复提交支付请求&…

Pull Request记录与Git commit签名

Pull Request记录 好久没有pull request了&#xff0c;浅浅记录一下流程 &#xff1a;Fork 原项目&#xff08;如果你没有写权限&#xff09;&#xff1a;打开原项目主页&#xff08;例如&#xff1a;github.com/your-professor/research-topic&#xff09;&#xff0c;点击右…

如何在C++交易系统中集成高性能回测与模拟撮合

DolphinDB 的高性能行情回放与模拟撮合引擎插件&#xff0c;为量化交易者提供了低延迟、高吞吐量的策略验证解决方案。对于已构建 C 回测框架的机构而言&#xff0c;直接在现有系统中集成撮合引擎&#xff0c;既能复用既有基础设施&#xff0c;又能获得 DolphinDB 的极速计算优…

【Laravel】 Laravel 智能验证规则生成器

Laravel 智能验证规则生成器:企业级增强方案 <?phpnamespace App\Services\Validation;use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; use Illuminate\Validation\…

讲基于优化的 IMU 与视觉信息融合

目录 视觉 SLAM 里的 Bundle Adjustment 问题 最小二乘基础概念 迭代下降法求解:下降法 最速下降法和牛顿法 阻尼法 非线性最小二乘 Gauss-Newton 和 LM 鲁棒核函数的实现 VIO 残差函数的构建 视觉重投影误差 IMU 测量值积分 状态误差线性递推公式的推导 基于误差随时间变化的…

洛谷P1107 [BJWC2008] 雷涛的小猫

洛谷P1107 [BJWC2008] 雷涛的小猫 洛谷题目传送门 题目背景 原最大整数参见 P1012 题目描述 雷涛同学非常的有爱心&#xff0c;在他的宿舍里&#xff0c;养着一只因为受伤被救助的小猫&#xff08;当然&#xff0c;这样的行为是违反学生宿舍管理条例的&#xff09;。在他的…

ROS2---话题重映射

一、话题重映射的基本概念 在 ROS2&#xff08;Robot Operating System 2&#xff09;中&#xff0c;话题重映射&#xff08;Topic Remapping&#xff09; 是一种灵活的机制&#xff0c;允许用户在不修改代码的情况下&#xff0c;改变节点发布或订阅的话题名称。这一机制在多机…

IOday4——7.3

1.思维导图 2.创建一个分支线程&#xff0c;在主线程中拷贝文件的前一部分&#xff0c;主线程拷贝文件的后一部分。 3.解读代码 info1 from child process_1 info2 from child process_1 info1 from child process_2 info1 from parent process 4.解读代码&#xff0c;打印…

[特殊字符] Excel 提取+图片批量插入 | Python 自动化生成稽查报告 Word 模板

本篇教程展示如何利用 Python&#xff0c;实现从 Excel 中提取稽查问题数据&#xff0c;并将对应图片按顺序插入到 Word 模板表格里&#xff0c;最终生成一份图文并茂的稽查报告。 目录 &#x1f4dd; Step 1&#xff1a;从 Excel 提取稽查问题数据 &#x1f5bc; Step 2&am…

【libm】 7 双精度正弦函数 (k_sin.rs)

一、源码 这段代码实现了一个高精度的正弦函数计算核心&#xff08;kernel sin function&#xff09;&#xff0c;用于计算在区间约[-π/4, π/4]内的正弦值。 // origin: FreeBSD /usr/src/lib/msun/src/k_sin.c // // // Copyright (C) 1993 by Sun Microsystems, Inc. Al…