首页 > 解决方案 > 使用 ThreadLocal 进行数据的请求范围传递

问题描述

我使用 Spring Boot 2 制作了一个 Java 8 REST API。控制器端点可以使用自定义注解进行注解@DataAware。有一个 HandlerInterceptor active 检查当前请求是否映射到具有此注释的方法。如果是,我希望拦截器解析请求的某个标头,并使生成的对象在处理该请求的整个线程中可用。

例如:

  1. 请求包含标头“specialData a:b:c”
  2. 端点带有注释@DataAware
  3. DataInterceptor解析头部并创建一个对象List parsedData = "a", "b" and "c"。
  4. DataInterceptor会做类似 的事情ThreadForThisRequest.addProperty("data",myParsedData);
  5. 在我的应用程序的各个地方,类和对象需要能够引用 parsedData,并且应该使用当前在该线程上处于活动状态的值。
  6. 当另一个请求进入系统时(可能同时),两个线程应该看不到对方的解析数据。如果重复使用相同的线程,则应删除或覆盖先前存储的数据

为此,我想使用 MDC(映射诊断上下文),但将数据存储在相对隐藏的“全局”上下文映射中似乎是一种反模式。

我不喜欢请求属性,因为那样我将不得不在我的应用程序中的任何地方传递请求对象。编写看起来像“public static final XXX”的东西要容易得多,但实际上只限于该请求(线程)。

我偶然发现了 ThreadLocal,并想确定它是否按照我的想法进行。如果我介绍以下领域:

public static ThreadLocal<List<String>> requestSpecificData

那么每次我的应用程序使用这个对象时,只会给出那个请求的数据,因为每个请求都是由它自己的线程处理的?Spring Web 或 Spring Boot 的嵌入式 Tomcat 是否使用线程或转发请求(到其他线程?)做一些其他古怪的事情,以便我的控制器端点可能丢失数据或看到以前的请求数据而不是它自己的数据?

标签: javaspringmultithreadingthread-localspring-web

解决方案


推荐阅读