mirror of
https://github.moeyy.xyz/https://github.com/GeWuYou/forgeboot
synced 2025-10-27 19:12:10 +08:00
feat(context): 重构上下文管理并添加序列化支持
- 新增 ContextHolder 类,替换原有的 StringContextHolder 对象 - 实现上下文值的序列化和反序列化 - 更新相关过滤器和装饰器以使用新的 ContextHolder- 添加获取指定类型值的方法- 实现 Context 接口的扩展方法,支持操作符重载
This commit is contained in:
parent
92b3eedb38
commit
7a6c371aa3
@ -26,7 +26,7 @@ abstract class AbstractContext<K, V>: Context<K, V> {
|
|||||||
* @param key 要查找的键
|
* @param key 要查找的键
|
||||||
* @return 对应的值,如果不存在则返回 null
|
* @return 对应的值,如果不存在则返回 null
|
||||||
*/
|
*/
|
||||||
override fun get(key: K): V? {
|
override fun retrieve(key: K): V? {
|
||||||
return local.get()[key]
|
return local.get()[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,16 @@ interface Context<K, V> {
|
|||||||
* @param key 要查找的键
|
* @param key 要查找的键
|
||||||
* @return 对应的值,如果不存在则返回 null
|
* @return 对应的值,如果不存在则返回 null
|
||||||
*/
|
*/
|
||||||
fun get(key: K): V?
|
fun retrieve(key: K): V?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据指定的键和类型从上下文中获取对应的值。
|
||||||
|
*
|
||||||
|
* @param key 要查找的键
|
||||||
|
* @param type 要转换的目标类型
|
||||||
|
* @return 对应类型的值,如果不存在或类型不匹配则返回 null
|
||||||
|
*/
|
||||||
|
fun <T> retrieveByType(key: K, type: Class<T>): T?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前上下文的一个快照,包含所有键值对。
|
* 获取当前上下文的一个快照,包含所有键值对。
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.api.extension
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.Context
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过操作符重载实现 Context 的 get 方法,用于根据指定的键获取对应的值。
|
||||||
|
*
|
||||||
|
* @param key 键,用于查找上下文中的值
|
||||||
|
* @return 返回与键对应的值,如果不存在则返回 null
|
||||||
|
*/
|
||||||
|
operator fun <K, V> Context<K, V>.get(key: K): V? {
|
||||||
|
return this.retrieve(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过操作符重载实现 Context 的 set 方法,用于将键值对存储到上下文中。
|
||||||
|
*
|
||||||
|
* @param key 键,用于标识要存储的值
|
||||||
|
* @param value 要存储的值,可以为 null
|
||||||
|
*/
|
||||||
|
operator fun <K, V> Context<K, V>.set(key: K, value: V?) {
|
||||||
|
this.put(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过操作符重载实现 Context 的 get 方法,用于根据指定的键和类型获取对应的值。
|
||||||
|
*
|
||||||
|
* @param key 键,用于查找上下文中的值
|
||||||
|
* @param type 指定的值类型,用于类型安全地获取值
|
||||||
|
* @return 返回与键和类型对应的值,如果不存在则返回 null
|
||||||
|
*/
|
||||||
|
operator fun <K, V, T> Context<K, V>.get(key: K, type: Class<T>) {
|
||||||
|
this.retrieveByType(key, type)
|
||||||
|
}
|
||||||
@ -10,4 +10,5 @@ dependencies {
|
|||||||
compileOnly(libs.springBootStarter.web)
|
compileOnly(libs.springBootStarter.web)
|
||||||
compileOnly(libs.springBootStarter.webflux)
|
compileOnly(libs.springBootStarter.webflux)
|
||||||
compileOnly(libs.springCloudStarter.openfeign)
|
compileOnly(libs.springCloudStarter.openfeign)
|
||||||
|
api(project(Modules.Core.SERIALIZATION))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,26 @@
|
|||||||
package com.gewuyou.forgeboot.context.autoconfigure
|
package com.gewuyou.forgeboot.context.autoconfigure
|
||||||
|
|
||||||
|
|
||||||
import com.gewuyou.forgeboot.context.api.*
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import com.gewuyou.forgeboot.context.impl.*
|
import com.gewuyou.forgeboot.context.api.ContextFieldContributor
|
||||||
|
import com.gewuyou.forgeboot.context.api.ContextProcessor
|
||||||
|
import com.gewuyou.forgeboot.context.api.FieldRegistry
|
||||||
|
import com.gewuyou.forgeboot.context.impl.ContextHolder
|
||||||
|
import com.gewuyou.forgeboot.context.impl.DefaultFieldRegistry
|
||||||
import com.gewuyou.forgeboot.context.impl.filter.ContextServletFilter
|
import com.gewuyou.forgeboot.context.impl.filter.ContextServletFilter
|
||||||
import com.gewuyou.forgeboot.context.impl.filter.ContextWebFilter
|
import com.gewuyou.forgeboot.context.impl.filter.ContextWebFilter
|
||||||
import com.gewuyou.forgeboot.context.impl.processor.*
|
import com.gewuyou.forgeboot.context.impl.processor.GeneratorProcessor
|
||||||
|
import com.gewuyou.forgeboot.context.impl.processor.HeaderProcessor
|
||||||
|
import com.gewuyou.forgeboot.context.impl.processor.MdcProcessor
|
||||||
|
import com.gewuyou.forgeboot.context.impl.processor.ReactorProcessor
|
||||||
|
import com.gewuyou.forgeboot.core.serialization.serializer.ValueSerializer
|
||||||
|
import com.gewuyou.forgeboot.core.serialization.serializer.impl.serializer.JacksonValueSerializer
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||||
|
import org.springframework.boot.web.reactive.function.client.WebClientCustomizer
|
||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
import org.springframework.boot.autoconfigure.condition.*
|
|
||||||
import org.springframework.boot.web.reactive.function.client.WebClientCustomizer
|
|
||||||
import org.springframework.core.task.TaskDecorator
|
import org.springframework.core.task.TaskDecorator
|
||||||
import org.springframework.web.reactive.function.client.ClientRequest
|
import org.springframework.web.reactive.function.client.ClientRequest
|
||||||
|
|
||||||
@ -26,6 +35,17 @@ import org.springframework.web.reactive.function.client.ClientRequest
|
|||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
class ForgeContextAutoConfiguration {
|
class ForgeContextAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
fun valueSerializer(objectMapper: ObjectMapper): ValueSerializer{
|
||||||
|
return JacksonValueSerializer(objectMapper)
|
||||||
|
}
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
fun contextHolder(valueSerializer: ValueSerializer): ContextHolder {
|
||||||
|
return ContextHolder(valueSerializer)
|
||||||
|
}
|
||||||
/* ───────────────────────────────────────────────────────────────
|
/* ───────────────────────────────────────────────────────────────
|
||||||
0️⃣ 通用 Bean:不依赖 Web / Feign / Reactor 等外部包
|
0️⃣ 通用 Bean:不依赖 Web / Feign / Reactor 等外部包
|
||||||
─────────────────────────────────────────────────────────────── */
|
─────────────────────────────────────────────────────────────── */
|
||||||
@ -171,13 +191,14 @@ class ForgeContextAutoConfiguration {
|
|||||||
* 拦截器会在每次 Feign 请求发起前,将当前上下文字段写入 HTTP 请求头。
|
* 拦截器会在每次 Feign 请求发起前,将当前上下文字段写入 HTTP 请求头。
|
||||||
*
|
*
|
||||||
* @param registry 字段注册表
|
* @param registry 字段注册表
|
||||||
|
* @param contextHolder 上下文持有者
|
||||||
* @return 构建完成的 feign.RequestInterceptor 实例
|
* @return 构建完成的 feign.RequestInterceptor 实例
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
fun feignInterceptor(registry: FieldRegistry) =
|
fun feignInterceptor(registry: FieldRegistry,contextHolder: ContextHolder) =
|
||||||
feign.RequestInterceptor { tpl ->
|
feign.RequestInterceptor { tpl ->
|
||||||
val ctx = StringContextHolder.snapshot()
|
val ctx = contextHolder.snapshot()
|
||||||
registry.all().forEach { def ->
|
registry.all().forEach { def ->
|
||||||
ctx[def.key]?.let { tpl.header(def.header, it) }
|
ctx[def.key]?.let { tpl.header(def.header, it) }
|
||||||
}
|
}
|
||||||
@ -200,20 +221,21 @@ class ForgeContextAutoConfiguration {
|
|||||||
* 通过装饰线程池任务,确保异步任务继承调用线程的上下文状态。
|
* 通过装饰线程池任务,确保异步任务继承调用线程的上下文状态。
|
||||||
*
|
*
|
||||||
* @param processors 所有处理器列表
|
* @param processors 所有处理器列表
|
||||||
|
* @param contextHolder 上下文持有者
|
||||||
* @return 构建完成的 TaskDecorator 实例
|
* @return 构建完成的 TaskDecorator 实例
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
fun contextTaskDecorator(processors: List<ContextProcessor>) =
|
fun contextTaskDecorator(processors: List<ContextProcessor>,contextHolder: ContextHolder) =
|
||||||
TaskDecorator { delegate ->
|
TaskDecorator { delegate ->
|
||||||
val snap = StringContextHolder.snapshot()
|
val snap = contextHolder.snapshot()
|
||||||
Runnable {
|
Runnable {
|
||||||
try {
|
try {
|
||||||
snap.forEach(StringContextHolder::put)
|
snap.forEach(contextHolder::put)
|
||||||
processors.forEach { it.inject(Unit, snap.toMutableMap()) }
|
processors.forEach { it.inject(Unit, snap.toMutableMap()) }
|
||||||
delegate.run()
|
delegate.run()
|
||||||
} finally {
|
} finally {
|
||||||
processors.forEach { it.inject(Unit, mutableMapOf()) }
|
processors.forEach { it.inject(Unit, mutableMapOf()) }
|
||||||
StringContextHolder.clear()
|
contextHolder.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,13 +256,13 @@ class ForgeContextAutoConfiguration {
|
|||||||
* 注册 WebClientCustomizer,用于定制 WebClient 的请求行为。
|
* 注册 WebClientCustomizer,用于定制 WebClient 的请求行为。
|
||||||
*
|
*
|
||||||
* 在每次请求发出前,将当前上下文字段写入 HTTP 请求头。
|
* 在每次请求发出前,将当前上下文字段写入 HTTP 请求头。
|
||||||
*
|
*@param contextHolder 上下文持有者
|
||||||
* @return 构建完成的 WebClientCustomizer 实例
|
* @return 构建完成的 WebClientCustomizer 实例
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
fun contextWebClientCustomizer() = WebClientCustomizer { builder ->
|
fun contextWebClientCustomizer(contextHolder: ContextHolder) = WebClientCustomizer { builder ->
|
||||||
builder.filter { req, next ->
|
builder.filter { req, next ->
|
||||||
val ctx = StringContextHolder.snapshot()
|
val ctx = contextHolder.snapshot()
|
||||||
val mutated = ClientRequest.from(req).apply {
|
val mutated = ClientRequest.from(req).apply {
|
||||||
registry.all().forEach { def ->
|
registry.all().forEach { def ->
|
||||||
ctx[def.key]?.let { value -> header(def.header, value) }
|
ctx[def.key]?.let { value -> header(def.header, value) }
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(project(Modules.Context.API))
|
compileOnly(project(Modules.Context.API))
|
||||||
|
compileOnly(project(Modules.Core.SERIALIZATION))
|
||||||
compileOnly(libs.springBootStarter.web)
|
compileOnly(libs.springBootStarter.web)
|
||||||
compileOnly(libs.springBootStarter.webflux)
|
compileOnly(libs.springBootStarter.webflux)
|
||||||
implementation(platform(libs.springBootDependencies.bom))
|
implementation(platform(libs.springBootDependencies.bom))
|
||||||
implementation(libs.springBoot.autoconfigure)
|
implementation(libs.springBoot.autoconfigure)
|
||||||
|
implementation(libs.jackson.databind)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.impl
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.AbstractContext
|
||||||
|
import com.gewuyou.forgeboot.core.serialization.serializer.ValueSerializer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上下文容器,用于存储和获取键值对形式的字符串数据。
|
||||||
|
*
|
||||||
|
* @since 2025-06-04 15:05:43
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
open class ContextHolder(
|
||||||
|
private val valueSerializer: ValueSerializer
|
||||||
|
) : AbstractContext<String, String>() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储键值对到上下文中。如果值为 null,则不会存储。
|
||||||
|
*
|
||||||
|
* @param key 要存储的键
|
||||||
|
* @param value 要存储的值,可以为 null
|
||||||
|
*/
|
||||||
|
open fun put(key: String, value: Any?) {
|
||||||
|
super.put(key, value?.let { valueSerializer.serialize(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据指定的键和类型从上下文中获取对应的值。
|
||||||
|
*
|
||||||
|
* @param key 要查找的键
|
||||||
|
* @param type 要转换的目标类型
|
||||||
|
* @return 对应类型的值,如果不存在或类型不匹配则返回 null
|
||||||
|
*/
|
||||||
|
override fun <T> retrieveByType(key: String, type: Class<T>): T? {
|
||||||
|
return retrieve(key)?.let { valueSerializer.deserialize(it, type) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
package com.gewuyou.forgeboot.context.impl
|
|
||||||
|
|
||||||
import com.gewuyou.forgeboot.context.api.AbstractContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
*字符串上下文容器
|
|
||||||
*
|
|
||||||
* @since 2025-06-04 15:05:43
|
|
||||||
* @author gewuyou
|
|
||||||
*/
|
|
||||||
object StringContextHolder: AbstractContext<String, String>()
|
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.impl.extension
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.Context
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过操作符重载实现 Context 的 get 方法,用于根据指定的键获取对应的值。
|
||||||
|
*
|
||||||
|
* @param key 键,用于查找上下文中的值
|
||||||
|
* @return 返回与键对应的值,如果不存在则返回 null
|
||||||
|
*/
|
||||||
|
operator fun <K, V> Context<K, V>.get(key: K): V? {
|
||||||
|
return this.retrieve(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过操作符重载实现 Context 的 set 方法,用于将键值对存储到上下文中。
|
||||||
|
*
|
||||||
|
* @param key 键,用于标识要存储的值
|
||||||
|
* @param value 要存储的值,可以为 null
|
||||||
|
*/
|
||||||
|
operator fun <K, V> Context<K, V>.set(key: K, value: V?) {
|
||||||
|
this.put(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过操作符重载实现 Context 的 get 方法,用于根据指定的键和类型获取对应的值。
|
||||||
|
*
|
||||||
|
* @param key 键,用于查找上下文中的值
|
||||||
|
* @param type 指定的值类型,用于类型安全地获取值
|
||||||
|
* @return 返回与键和类型对应的值,如果不存在则返回 null
|
||||||
|
*/
|
||||||
|
operator fun <K, V, T> Context<K, V>.get(key: K, type: Class<T>) {
|
||||||
|
this.retrieveByType(key, type)
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.impl.extension
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.impl.ContextHolder
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为ContextHolder实现赋值操作符的重写方法
|
||||||
|
*
|
||||||
|
* @param key 存储值的键,用于后续从上下文获取值时使用
|
||||||
|
* @param value 需要存储在ContextHolder中的值,允许为null
|
||||||
|
*/
|
||||||
|
operator fun ContextHolder.set(key: String, value: Any?) {
|
||||||
|
this.put(key, value)
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
package com.gewuyou.forgeboot.context.impl.filter
|
package com.gewuyou.forgeboot.context.impl.filter
|
||||||
|
|
||||||
import com.gewuyou.forgeboot.context.api.ContextProcessor
|
import com.gewuyou.forgeboot.context.api.ContextProcessor
|
||||||
import com.gewuyou.forgeboot.context.impl.StringContextHolder
|
import com.gewuyou.forgeboot.context.impl.ContextHolder
|
||||||
import jakarta.servlet.FilterChain
|
import jakarta.servlet.FilterChain
|
||||||
import jakarta.servlet.http.HttpServletRequest
|
import jakarta.servlet.http.HttpServletRequest
|
||||||
import jakarta.servlet.http.HttpServletResponse
|
import jakarta.servlet.http.HttpServletResponse
|
||||||
@ -20,6 +20,7 @@ import org.springframework.web.filter.OncePerRequestFilter
|
|||||||
*/
|
*/
|
||||||
class ContextServletFilter(
|
class ContextServletFilter(
|
||||||
private val chain: List<ContextProcessor>,
|
private val chain: List<ContextProcessor>,
|
||||||
|
private val contextHolder: ContextHolder
|
||||||
) : OncePerRequestFilter() {
|
) : OncePerRequestFilter() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,13 +39,13 @@ class ContextServletFilter(
|
|||||||
filterChain: FilterChain,
|
filterChain: FilterChain,
|
||||||
) {
|
) {
|
||||||
// 创建当前线程上下文快照的可变副本,确保后续操作不影响原始上下文
|
// 创建当前线程上下文快照的可变副本,确保后续操作不影响原始上下文
|
||||||
val ctx = StringContextHolder.snapshot().toMutableMap()
|
val ctx = contextHolder.snapshot().toMutableMap()
|
||||||
|
|
||||||
// 遍历上下文处理器链,依次从请求中提取上下文信息并更新临时上下文容器
|
// 遍历上下文处理器链,依次从请求中提取上下文信息并更新临时上下文容器
|
||||||
chain.forEach { it.extract(request, ctx) }
|
chain.forEach { it.extract(request, ctx) }
|
||||||
|
|
||||||
// 将提取后的上下文写入当前线程的上下文持有者,供后续组件访问
|
// 将提取后的上下文写入当前线程的上下文持有者,供后续组件访问
|
||||||
ctx.forEach(StringContextHolder::put)
|
ctx.forEach(contextHolder::put)
|
||||||
|
|
||||||
// 调用下一个过滤器或最终的目标处理器
|
// 调用下一个过滤器或最终的目标处理器
|
||||||
chain.forEach { it.inject(request, ctx) }
|
chain.forEach { it.inject(request, ctx) }
|
||||||
@ -56,7 +57,7 @@ class ContextServletFilter(
|
|||||||
// 向处理器链注入空上下文,触发清理操作(如有)
|
// 向处理器链注入空上下文,触发清理操作(如有)
|
||||||
chain.forEach { it.inject(Unit, mutableMapOf()) }
|
chain.forEach { it.inject(Unit, mutableMapOf()) }
|
||||||
// 显式清除当前线程的上下文持有者,防止上下文泄露
|
// 显式清除当前线程的上下文持有者,防止上下文泄露
|
||||||
StringContextHolder.clear()
|
contextHolder.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
package com.gewuyou.forgeboot.context.impl.filter
|
package com.gewuyou.forgeboot.context.impl.filter
|
||||||
|
|
||||||
import com.gewuyou.forgeboot.context.api.ContextProcessor
|
import com.gewuyou.forgeboot.context.api.ContextProcessor
|
||||||
import com.gewuyou.forgeboot.context.impl.StringContextHolder
|
import com.gewuyou.forgeboot.context.impl.ContextHolder
|
||||||
import com.gewuyou.forgeboot.context.impl.processor.ReactorProcessor
|
import com.gewuyou.forgeboot.context.impl.processor.ReactorProcessor
|
||||||
import org.springframework.web.server.ServerWebExchange
|
import org.springframework.web.server.ServerWebExchange
|
||||||
import org.springframework.web.server.WebFilter
|
import org.springframework.web.server.WebFilter
|
||||||
@ -22,7 +22,8 @@ import reactor.core.publisher.Mono
|
|||||||
*/
|
*/
|
||||||
class ContextWebFilter(
|
class ContextWebFilter(
|
||||||
private val contextProcessors: List<ContextProcessor>,
|
private val contextProcessors: List<ContextProcessor>,
|
||||||
private val reactorProc: ReactorProcessor
|
private val reactorProc: ReactorProcessor,
|
||||||
|
private val contextHolder: ContextHolder
|
||||||
) : WebFilter {
|
) : WebFilter {
|
||||||
/**
|
/**
|
||||||
* 执行过滤逻辑,在请求链中插入上下文管理操作。
|
* 执行过滤逻辑,在请求链中插入上下文管理操作。
|
||||||
@ -42,12 +43,12 @@ class ContextWebFilter(
|
|||||||
exchange: ServerWebExchange,
|
exchange: ServerWebExchange,
|
||||||
chain: WebFilterChain,
|
chain: WebFilterChain,
|
||||||
): Mono<Void> {
|
): Mono<Void> {
|
||||||
// 从 StringContextHolder 快照获取当前上下文并转换为可变 Map
|
// 从 ContextHolder 快照获取当前上下文并转换为可变 Map
|
||||||
val ctx = StringContextHolder.snapshot().toMutableMap()
|
val ctx = contextHolder.snapshot().toMutableMap()
|
||||||
// 遍历所有 ContextProcessor,从请求中提取上下文信息到 ctx
|
// 遍历所有 ContextProcessor,从请求中提取上下文信息到 ctx
|
||||||
contextProcessors.forEach { it.extract(exchange, ctx) }
|
contextProcessors.forEach { it.extract(exchange, ctx) }
|
||||||
// 将上下文写入 StringContextHolder(ThreadLocal)
|
// 将上下文写入 ContextHolder(ThreadLocal)
|
||||||
ctx.forEach(StringContextHolder::put)
|
ctx.forEach(contextHolder::put)
|
||||||
// 使用 MdcProcessor 将上下文注入到 MDC 中
|
// 使用 MdcProcessor 将上下文注入到 MDC 中
|
||||||
contextProcessors.forEach { it.inject(Unit, ctx) }
|
contextProcessors.forEach { it.inject(Unit, ctx) }
|
||||||
// 构建新的 ServerWebExchange 实例
|
// 构建新的 ServerWebExchange 实例
|
||||||
@ -60,7 +61,7 @@ class ContextWebFilter(
|
|||||||
.doFinally {
|
.doFinally {
|
||||||
// 清理 ThreadLocal + MDC 上下文
|
// 清理 ThreadLocal + MDC 上下文
|
||||||
contextProcessors.forEach { it.inject(Unit, mutableMapOf()) }
|
contextProcessors.forEach { it.inject(Unit, mutableMapOf()) }
|
||||||
StringContextHolder.clear()
|
contextHolder.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user