mirror of
https://github.moeyy.xyz/https://github.com/GeWuYou/forgeboot
synced 2025-10-27 16:02:11 +08:00
refactor(context): 将 ForgeContextAutoConfiguration 拆分为多个自动配置类
- 新增 ContextCommonAutoConfiguration、ContextProcessorAutoConfiguration、ContextReactorAutoConfiguration、ContextServletAutoConfiguration、ContextWebFluxAutoConfiguration、ContextFeignAutoConfiguration、ContextTaskDecoratorAutoConfiguration 和 ContextWebClientAutoConfiguration - 删除 ForgeContextAutoConfiguration 类 - 更新 AutoConfiguration.imports 文件,添加新的自动配置类
This commit is contained in:
parent
9c11b7e2e5
commit
5f3ae7a5cd
@ -0,0 +1,69 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.autoconfigure
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import com.gewuyou.forgeboot.context.api.ContextFieldContributor
|
||||||
|
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.core.serialization.serializer.ValueSerializer
|
||||||
|
import com.gewuyou.forgeboot.core.serialization.serializer.impl.serializer.JacksonValueSerializer
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context Common 自动配置
|
||||||
|
*
|
||||||
|
* 该配置类定义了上下文模块的基础 Bean,包括序列化器、上下文持有者、字段注册表以及多种处理器。
|
||||||
|
* 所有 Bean 均使用 @ConditionalOnMissingBean 注解以确保仅在容器中没有其他同类型 Bean 时才创建。
|
||||||
|
*
|
||||||
|
* @since 2025-06-24 22:09:55
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
class ContextCommonAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 ValueSerializer Bean,用于在缺少其他实现时提供默认的值序列化器。
|
||||||
|
*
|
||||||
|
* 该方法定义了一个 JacksonValueSerializer 实例作为默认的 ValueSerializer 实现,
|
||||||
|
* 负责使用 Jackson 库对上下文字段值进行序列化和反序列化操作。
|
||||||
|
*
|
||||||
|
* @param objectMapper 提供 JSON 序列化支持的 ObjectMapper 实例
|
||||||
|
* @return 构建完成的 ValueSerializer 实例
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
fun valueSerializer(objectMapper: ObjectMapper): ValueSerializer {
|
||||||
|
return JacksonValueSerializer(objectMapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 ContextHolder Bean,用于在缺少其他实现时提供默认的上下文持有者。
|
||||||
|
*
|
||||||
|
* 该方法定义了一个 ContextHolder 实例作为默认的上下文管理器,
|
||||||
|
* 负责存储、传递和清理当前线程的上下文字段数据。
|
||||||
|
*
|
||||||
|
* @param valueSerializer 提供值序列化支持的 ValueSerializer 实例
|
||||||
|
* @return 构建完成的 ContextHolder 实例
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
fun contextHolder(valueSerializer: ValueSerializer): ContextHolder {
|
||||||
|
return ContextHolder(valueSerializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 FieldRegistry Bean,用于注册上下文中所有字段定义。
|
||||||
|
*
|
||||||
|
* FieldRegistry 是上下文字段的核心注册中心,聚合所有 ContextFieldContributor 提供的字段定义。
|
||||||
|
*
|
||||||
|
* @param contributors 提供字段定义的贡献者列表
|
||||||
|
* @return 构建完成的 FieldRegistry 实例
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
fun fieldRegistry(contributors: List<ContextFieldContributor>): FieldRegistry =
|
||||||
|
DefaultFieldRegistry(contributors.flatMap { it.fields() }.toSet())
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.autoconfigure
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.FieldRegistry
|
||||||
|
import com.gewuyou.forgeboot.context.impl.ContextHolder
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上下文Feign自动配置类
|
||||||
|
*
|
||||||
|
* 该配置类用于在Spring Boot应用中自动装配与上下文传播相关的Feign拦截器。
|
||||||
|
* 当Feign库存在时,该配置会创建一个请求拦截器,用于在Feign调用过程中传播上下文字段。
|
||||||
|
*
|
||||||
|
* @since 2025-06-24 22:17:46
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(name = ["feign.RequestInterceptor"])
|
||||||
|
class ContextFeignAutoConfiguration {
|
||||||
|
/**
|
||||||
|
* 创建 Feign 请求拦截器 Bean。
|
||||||
|
*
|
||||||
|
* 该拦截器会在每次 Feign 请求发起前执行,将当前上下文中的字段值写入 HTTP 请求头,
|
||||||
|
* 以支持跨服务调用的上下文传播。
|
||||||
|
*
|
||||||
|
* @param registry 字段注册表,用于获取需要传播的字段定义
|
||||||
|
* @param contextHolder 上下文持有者,用于获取当前线程的上下文快照
|
||||||
|
* @return 构建完成的 feign.RequestInterceptor 实例
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
fun feignInterceptor(registry: FieldRegistry, contextHolder: ContextHolder) =
|
||||||
|
feign.RequestInterceptor { tpl ->
|
||||||
|
// 获取当前上下文快照
|
||||||
|
val ctx = contextHolder.snapshot()
|
||||||
|
// 遍历所有已注册的字段定义
|
||||||
|
registry.all().forEach { def ->
|
||||||
|
// 如果当前字段有值,则将其添加到 HTTP 请求头中
|
||||||
|
ctx[def.key]?.let { tpl.header(def.header, it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.autoconfigure
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.FieldRegistry
|
||||||
|
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 org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上下文处理器自动配置
|
||||||
|
*
|
||||||
|
* 该配置类定义了多个上下文处理相关的 Bean,用于支持线程上下文字段的提取、生成和日志集成。
|
||||||
|
*
|
||||||
|
* @since 2025-06-24 22:12:58
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
class ContextProcessorAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 HeaderProcessor Bean,用于处理请求头中的上下文字段。
|
||||||
|
*
|
||||||
|
* HeaderProcessor 负责从请求头中提取上下文字段并注入到当前线程上下文中。
|
||||||
|
*
|
||||||
|
* @param reg 字段注册表,用于获取需要处理的上下文字段定义
|
||||||
|
* @return 构建完成的 HeaderProcessor 实例
|
||||||
|
*/
|
||||||
|
@Bean("headerProcessor")
|
||||||
|
fun headerProcessor(reg: FieldRegistry): HeaderProcessor {
|
||||||
|
return HeaderProcessor(reg)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 GeneratorProcessor Bean,用于生成上下文字段值。
|
||||||
|
*
|
||||||
|
* GeneratorProcessor 根据字段定义生成默认值(如 traceId、spanId 等),适用于首次进入系统的情况。
|
||||||
|
*
|
||||||
|
* @param reg 字段注册表,用于获取需要生成值的上下文字段定义
|
||||||
|
* @return 构建完成的 GeneratorProcessor 实例
|
||||||
|
*/
|
||||||
|
@Bean("generatorProcessor")
|
||||||
|
fun generatorProcessor(reg: FieldRegistry): GeneratorProcessor {
|
||||||
|
return GeneratorProcessor(reg)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 MdcProcessor Bean,用于将上下文字段写入 MDC(Mapped Diagnostic Context)。
|
||||||
|
*
|
||||||
|
* MdcProcessor 使得日志框架(如 Logback)可以访问当前上下文字段,便于日志追踪。
|
||||||
|
*
|
||||||
|
* @param reg 字段注册表,用于获取需要写入 MDC 的上下文字段定义
|
||||||
|
* @return 构建完成的 MdcProcessor 实例
|
||||||
|
*/
|
||||||
|
@Bean("mdcProcessor")
|
||||||
|
fun mdcProcessor(reg: FieldRegistry): MdcProcessor {
|
||||||
|
return MdcProcessor(reg)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.autoconfigure
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.FieldRegistry
|
||||||
|
import com.gewuyou.forgeboot.context.impl.processor.ReactorProcessor
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context Reactor 自动配置
|
||||||
|
*
|
||||||
|
* 该配置类用于在 Spring Boot 环境中自动装配 ReactorProcessor Bean。
|
||||||
|
* 只有在 classpath 中存在 reactor.util.context.Context 类时才会生效。
|
||||||
|
*
|
||||||
|
* @since 2025-06-24 22:14:18
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(name = ["reactor.util.context.Context"])
|
||||||
|
class ContextReactorAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建并配置 ReactorProcessor Bean
|
||||||
|
*
|
||||||
|
* 该方法定义了一个名为 "reactorProcessor" 的 Spring Bean,
|
||||||
|
* 用于在 Reactor 响应式流的上下文中传播和管理自定义上下文字段。
|
||||||
|
*
|
||||||
|
* @param reg FieldRegistry 实例,用于注册和管理上下文字段
|
||||||
|
* @return 配置完成的 ReactorProcessor 实例
|
||||||
|
*/
|
||||||
|
@Bean("reactorProcessor")
|
||||||
|
fun reactorProcessor(reg: FieldRegistry) = ReactorProcessor(reg)
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.autoconfigure
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.ContextProcessor
|
||||||
|
import com.gewuyou.forgeboot.context.impl.ContextHolder
|
||||||
|
import com.gewuyou.forgeboot.context.impl.filter.ContextServletFilter
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.core.Ordered
|
||||||
|
import org.springframework.core.annotation.Order
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上下文 Servlet 自动配置类
|
||||||
|
*
|
||||||
|
* 该配置类用于在基于 Servlet 的 Web 应用中自动装配上下文传播相关的组件。
|
||||||
|
* 主要功能包括:
|
||||||
|
* - 在满足 Servlet 环境条件时启用配置
|
||||||
|
* - 注册 ContextServletFilter Bean 以支持请求链中的上下文一致性维护
|
||||||
|
*
|
||||||
|
* @since 2025-06-24 22:15:23
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "servlet", matchIfMissing = true)
|
||||||
|
@ConditionalOnClass(name = ["jakarta.servlet.Filter"])
|
||||||
|
class ContextServletAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建并注册 ContextServletFilter 实例
|
||||||
|
*
|
||||||
|
* 此方法创建一个用于同步阻塞的 Servlet 请求链中的上下文传播过滤器。
|
||||||
|
* 只有在容器中尚未存在相同类型的 Bean 时才会注册。
|
||||||
|
*
|
||||||
|
* @param chain 处理器链,包含多个 ContextProcessor 实例
|
||||||
|
* @param contextHolder 上下文持有者,用于存储和传递上下文数据
|
||||||
|
* @return 构建完成的 ContextServletFilter 实例
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
|
||||||
|
fun contextServletFilter(chain: List<ContextProcessor>, contextHolder: ContextHolder) =
|
||||||
|
ContextServletFilter(chain, contextHolder)
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.autoconfigure
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.ContextProcessor
|
||||||
|
import com.gewuyou.forgeboot.context.impl.ContextHolder
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.core.task.TaskDecorator
|
||||||
|
import kotlin.collections.forEach
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context Task Decorator 自动配置
|
||||||
|
*
|
||||||
|
* 用于自动装配一个 TaskDecorator Bean,确保异步任务执行时能够继承和保持上下文一致性。
|
||||||
|
* 通过注入处理器链和上下文持有者,实现上下文的捕获、传递和清理。
|
||||||
|
*
|
||||||
|
* @since 2025-06-24 22:18:51
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
class ContextTaskDecoratorAutoConfiguration {
|
||||||
|
/**
|
||||||
|
* 创建 TaskDecorator Bean,用于在异步执行中保持上下文一致性。
|
||||||
|
*
|
||||||
|
* 通过装饰线程池任务,确保异步任务继承调用线程的上下文状态。
|
||||||
|
* 此方法会注入所有可用的 ContextProcessor 来处理上下文注入逻辑。
|
||||||
|
*
|
||||||
|
* @param processors 所有处理器列表,用于上下文注入操作
|
||||||
|
* @param contextHolder 上下文持有者,用于获取和存储当前线程的上下文快照
|
||||||
|
* @return 构建完成的 TaskDecorator 实例,用于装饰异步任务
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
fun contextTaskDecorator(processors: List<ContextProcessor>, contextHolder: ContextHolder) =
|
||||||
|
TaskDecorator { delegate ->
|
||||||
|
// 捕获当前线程的上下文快照,用于传递给异步任务
|
||||||
|
val snap = contextHolder.snapshot()
|
||||||
|
Runnable {
|
||||||
|
try {
|
||||||
|
// 将快照内容重新放入当前线程的上下文持有者中
|
||||||
|
snap.forEach(contextHolder::put)
|
||||||
|
// 调用每个处理器的 inject 方法,将上下文数据注入到目标对象中
|
||||||
|
processors.forEach { it.inject(Unit, snap.toMutableMap()) }
|
||||||
|
// 执行被装饰的任务
|
||||||
|
delegate.run()
|
||||||
|
} finally {
|
||||||
|
// 清理当前线程的上下文注入数据,避免内存泄漏
|
||||||
|
processors.forEach { it.inject(Unit, mutableMapOf()) }
|
||||||
|
// 清空上下文持有者的全部数据
|
||||||
|
contextHolder.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.autoconfigure
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.FieldRegistry
|
||||||
|
import com.gewuyou.forgeboot.context.impl.ContextHolder
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||||
|
import org.springframework.boot.web.reactive.function.client.WebClientCustomizer
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.web.reactive.function.client.ClientRequest
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context Web Client 自动配置
|
||||||
|
*
|
||||||
|
* 配置 WebClient 请求行为,自动将上下文字段注入到 HTTP 请求头中。
|
||||||
|
* 适用于 Spring Boot 的 WebClient 请求定制场景。
|
||||||
|
*
|
||||||
|
* @since 2025-06-24 22:20:10
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(name = ["org.springframework.web.reactive.function.client.WebClient"])
|
||||||
|
class ContextWebClientAutoConfiguration {
|
||||||
|
/**
|
||||||
|
* 注册 WebClientCustomizer,用于定制 WebClient 的请求行为。
|
||||||
|
*
|
||||||
|
* 在每次请求发出前,将当前上下文字段写入 HTTP 请求头。
|
||||||
|
*
|
||||||
|
* @param contextHolder 上下文持有者,用于获取当前线程的上下文快照
|
||||||
|
* @param registry 字段注册器,用于获取需传递的上下文字段定义
|
||||||
|
* @return 构建完成的 WebClientCustomizer 实例
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
fun contextWebClientCustomizer(contextHolder: ContextHolder, registry: FieldRegistry) =
|
||||||
|
WebClientCustomizer { builder ->
|
||||||
|
// 添加过滤器,在请求发出前处理上下文注入逻辑
|
||||||
|
builder.filter { req, next ->
|
||||||
|
val ctx = contextHolder.snapshot() // 获取当前上下文快照
|
||||||
|
val mutated = ClientRequest.from(req).apply {
|
||||||
|
// 遍历所有注册字段定义,将上下文中的值注入到请求头中
|
||||||
|
registry.all().forEach { def ->
|
||||||
|
ctx[def.key]?.let { value -> header(def.header, value) }
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
next.exchange(mutated) // 执行修改后的请求
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.gewuyou.forgeboot.context.autoconfigure
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.context.api.ContextProcessor
|
||||||
|
import com.gewuyou.forgeboot.context.impl.ContextHolder
|
||||||
|
import com.gewuyou.forgeboot.context.impl.filter.ContextWebFilter
|
||||||
|
import com.gewuyou.forgeboot.context.impl.processor.ReactorProcessor
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.core.Ordered
|
||||||
|
import org.springframework.core.annotation.Order
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context Web Flux 自动配置
|
||||||
|
*
|
||||||
|
* 该配置类用于在 Spring WebFlux 环境下自动装配上下文传播相关的组件。
|
||||||
|
* 主要功能是注册 ContextWebFilter Bean,以确保请求链中上下文字段的一致性维护。
|
||||||
|
*
|
||||||
|
* @since 2025-06-24 22:16:19
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "reactive")
|
||||||
|
@ConditionalOnClass(name = ["org.springframework.web.server.WebFilter"])
|
||||||
|
class ContextWebFluxAutoConfiguration {
|
||||||
|
/**
|
||||||
|
* 注册 ContextWebFilter Bean,用于在 WebFlux 请求链中传播上下文字段。
|
||||||
|
*
|
||||||
|
* 该过滤器利用 ReactorProcessor 在 WebFlux 的过滤器链中维护上下文一致性。
|
||||||
|
* 参数 chain 提供了一组 ContextProcessor 实例,用于处理不同类型的上下文逻辑;
|
||||||
|
* reactorProcessor 是一个关键组件,负责实际的上下文传播和反应式流集成;
|
||||||
|
* contextHolder 存储了当前线程或请求的上下文数据,确保其在整个请求生命周期中可用。
|
||||||
|
*
|
||||||
|
* @param chain 处理器链,包含多个 ContextProcessor 实例
|
||||||
|
* @param reactorProcessor ReactorProcessor 实例,用于反应式上下文传播
|
||||||
|
* @param contextHolder 上下文持有者,用于存储和获取当前上下文
|
||||||
|
* @return 构建完成的 ContextWebFilter 实例
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
|
||||||
|
fun contextWebFilter(
|
||||||
|
chain: List<ContextProcessor>,
|
||||||
|
reactorProcessor: ReactorProcessor,
|
||||||
|
contextHolder: ContextHolder
|
||||||
|
) = ContextWebFilter(chain, reactorProcessor, contextHolder)
|
||||||
|
}
|
||||||
@ -1,295 +0,0 @@
|
|||||||
package com.gewuyou.forgeboot.context.autoconfigure
|
|
||||||
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
|
||||||
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.ContextWebFilter
|
|
||||||
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.Configuration
|
|
||||||
import org.springframework.core.task.TaskDecorator
|
|
||||||
import org.springframework.web.reactive.function.client.ClientRequest
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置类,用于自动配置上下文相关的 Bean。
|
|
||||||
*
|
|
||||||
* 该配置类根据不同的运行时依赖和配置条件,定义了一系列的 Bean,
|
|
||||||
* 实现了上下文字段在不同场景下的传播与管理机制。
|
|
||||||
*
|
|
||||||
* @since 2025-06-04 11:48:01
|
|
||||||
* @author gewuyou
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
class ForgeContextAutoConfiguration {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 ValueSerializer Bean,用于在缺少其他实现时提供默认的值序列化器。
|
|
||||||
*
|
|
||||||
* 该方法定义了一个 JacksonValueSerializer 实例作为默认的 ValueSerializer 实现,
|
|
||||||
* 负责使用 Jackson 库对上下文字段值进行序列化和反序列化操作。
|
|
||||||
*
|
|
||||||
* @param objectMapper 提供 JSON 序列化支持的 ObjectMapper 实例
|
|
||||||
* @return 构建完成的 ValueSerializer 实例
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
fun valueSerializer(objectMapper: ObjectMapper): ValueSerializer {
|
|
||||||
return JacksonValueSerializer(objectMapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 ContextHolder Bean,用于在缺少其他实现时提供默认的上下文持有者。
|
|
||||||
*
|
|
||||||
* 该方法定义了一个 ContextHolder 实例作为默认的上下文管理器,
|
|
||||||
* 负责存储、传递和清理当前线程的上下文字段数据。
|
|
||||||
*
|
|
||||||
* @param valueSerializer 提供值序列化支持的 ValueSerializer 实例
|
|
||||||
* @return 构建完成的 ContextHolder 实例
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
fun contextHolder(valueSerializer: ValueSerializer): ContextHolder {
|
|
||||||
return ContextHolder(valueSerializer)
|
|
||||||
}
|
|
||||||
/* ───────────────────────────────────────────────────────────────
|
|
||||||
0️⃣ 通用 Bean:不依赖 Web / Feign / Reactor 等外部包
|
|
||||||
─────────────────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 FieldRegistry Bean,用于注册上下文中所有字段定义。
|
|
||||||
*
|
|
||||||
* FieldRegistry 是上下文字段的核心注册中心,聚合所有 ContextFieldContributor 提供的字段定义。
|
|
||||||
*
|
|
||||||
* @param contributors 提供字段定义的贡献者列表
|
|
||||||
* @return 构建完成的 FieldRegistry 实例
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
fun fieldRegistry(contributors: List<ContextFieldContributor>): FieldRegistry =
|
|
||||||
DefaultFieldRegistry(contributors.flatMap { it.fields() }.toSet())
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 HeaderProcessor Bean,用于处理请求头中的上下文字段。
|
|
||||||
*
|
|
||||||
* HeaderProcessor 负责从请求头中提取上下文字段并注入到当前线程上下文中。
|
|
||||||
*
|
|
||||||
* @param reg 字段注册表
|
|
||||||
* @return 构建完成的 HeaderProcessor 实例
|
|
||||||
*/
|
|
||||||
@Bean("headerProcessor")
|
|
||||||
fun headerProcessor(reg: FieldRegistry) = HeaderProcessor(reg)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 GeneratorProcessor Bean,用于生成上下文字段值。
|
|
||||||
*
|
|
||||||
* GeneratorProcessor 根据字段定义生成默认值(如 traceId、spanId 等),适用于首次进入系统的情况。
|
|
||||||
*
|
|
||||||
* @param reg 字段注册表
|
|
||||||
* @return 构建完成的 GeneratorProcessor 实例
|
|
||||||
*/
|
|
||||||
@Bean("generatorProcessor")
|
|
||||||
fun generatorProcessor(reg: FieldRegistry) = GeneratorProcessor(reg)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 MdcProcessor Bean,用于将上下文字段写入 MDC(Mapped Diagnostic Context)。
|
|
||||||
*
|
|
||||||
* MdcProcessor 使得日志框架(如 Logback)可以访问当前上下文字段,便于日志追踪。
|
|
||||||
*
|
|
||||||
* @param reg 字段注册表
|
|
||||||
* @return 构建完成的 MdcProcessor 实例
|
|
||||||
*/
|
|
||||||
@Bean("mdcProcessor")
|
|
||||||
fun mdcProcessor(reg: FieldRegistry) = MdcProcessor(reg)
|
|
||||||
|
|
||||||
/* ───────────────────────────────────────────────────────────────
|
|
||||||
1️⃣ Reactor 支持(只有 classpath 有 Reactor 时才激活)
|
|
||||||
─────────────────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置类,提供对 Reactor 上下文传播的支持。
|
|
||||||
*/
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ConditionalOnClass(name = ["reactor.util.context.Context"])
|
|
||||||
class ReactorSupport {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 ReactorProcessor Bean,用于在 Reactor 上下文中传播上下文字段。
|
|
||||||
*
|
|
||||||
* ReactorProcessor 适配了 Reactor 的 Context 接口,确保上下文字段在响应式流中正确传递。
|
|
||||||
*
|
|
||||||
* @param reg 字段注册表
|
|
||||||
* @return 构建完成的 ReactorProcessor 实例
|
|
||||||
*/
|
|
||||||
@Bean("reactorProcessor")
|
|
||||||
fun reactorProcessor(reg: FieldRegistry) = ReactorProcessor(reg)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ───────────────────────────────────────────────────────────────
|
|
||||||
2️⃣ WebFlux 过滤器(依赖 WebFlux + Reactor)
|
|
||||||
─────────────────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置类,注册 WebFlux 环境下的上下文传播过滤器。
|
|
||||||
*/
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "reactive")
|
|
||||||
@ConditionalOnClass(name = ["org.springframework.web.server.WebFilter"])
|
|
||||||
class WebFluxPart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册 ContextWebFilter Bean,用于在 WebFlux 请求链中传播上下文字段。
|
|
||||||
*
|
|
||||||
* 该过滤器利用 ReactorProcessor 在 WebFlux 的过滤器链中维护上下文一致性。
|
|
||||||
*
|
|
||||||
* @param chain 处理器链
|
|
||||||
* @param reactorProcessor ReactorProcessor 实例
|
|
||||||
* @return 构建完成的 ContextWebFilter 实例
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
fun contextWebFilter(
|
|
||||||
chain: List<ContextProcessor>,
|
|
||||||
reactorProcessor: ReactorProcessor,
|
|
||||||
contextHolder: ContextHolder
|
|
||||||
) = ContextWebFilter(chain, reactorProcessor,contextHolder)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ───────────────────────────────────────────────────────────────
|
|
||||||
3️⃣ Servlet 过滤器(依赖 Servlet API)
|
|
||||||
─────────────────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置类,注册 Servlet 环境下的上下文传播过滤器。
|
|
||||||
*/
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ConditionalOnProperty(name = ["spring.main.web-application-type"], havingValue = "servlet", matchIfMissing = true)
|
|
||||||
@ConditionalOnClass(name = ["jakarta.servlet.Filter"])
|
|
||||||
class ServletPart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册 ContextServletFilter Bean,用于在 Servlet 请求链中传播上下文字段。
|
|
||||||
*
|
|
||||||
* 该过滤器负责在同步阻塞的 Servlet 请求链中维护上下文一致性。
|
|
||||||
*
|
|
||||||
* @param chain 处理器链
|
|
||||||
* @return 构建完成的 ContextServletFilter 实例
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
fun contextServletFilter(chain: List<ContextProcessor>,contextHolder: ContextHolder) =
|
|
||||||
ContextServletFilter(chain,contextHolder)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ───────────────────────────────────────────────────────────────
|
|
||||||
4️⃣ Feign 请求拦截器(依赖 OpenFeign)
|
|
||||||
─────────────────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置类,注册 Feign 客户端的请求拦截器。
|
|
||||||
*/
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ConditionalOnClass(name = ["feign.RequestInterceptor"])
|
|
||||||
class FeignPart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册 Feign 请求拦截器,用于在 Feign 调用中传播上下文字段。
|
|
||||||
*
|
|
||||||
* 拦截器会在每次 Feign 请求发起前,将当前上下文字段写入 HTTP 请求头。
|
|
||||||
*
|
|
||||||
* @param registry 字段注册表
|
|
||||||
* @param contextHolder 上下文持有者
|
|
||||||
* @return 构建完成的 feign.RequestInterceptor 实例
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
fun feignInterceptor(registry: FieldRegistry,contextHolder: ContextHolder) =
|
|
||||||
feign.RequestInterceptor { tpl ->
|
|
||||||
val ctx = contextHolder.snapshot()
|
|
||||||
registry.all().forEach { def ->
|
|
||||||
ctx[def.key]?.let { tpl.header(def.header, it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ───────────────────────────────────────────────────────────────
|
|
||||||
5️⃣ 线程池 TaskDecorator(纯 Spring,安全通用)
|
|
||||||
─────────────────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置类,注册异步执行上下文保持支持。
|
|
||||||
*/
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
class TaskDecoratorPart {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 TaskDecorator Bean,用于在异步执行中保持上下文一致性。
|
|
||||||
*
|
|
||||||
* 通过装饰线程池任务,确保异步任务继承调用线程的上下文状态。
|
|
||||||
*
|
|
||||||
* @param processors 所有处理器列表
|
|
||||||
* @param contextHolder 上下文持有者
|
|
||||||
* @return 构建完成的 TaskDecorator 实例
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
fun contextTaskDecorator(processors: List<ContextProcessor>,contextHolder: ContextHolder) =
|
|
||||||
TaskDecorator { delegate ->
|
|
||||||
val snap = contextHolder.snapshot()
|
|
||||||
Runnable {
|
|
||||||
try {
|
|
||||||
snap.forEach(contextHolder::put)
|
|
||||||
processors.forEach { it.inject(Unit, snap.toMutableMap()) }
|
|
||||||
delegate.run()
|
|
||||||
} finally {
|
|
||||||
processors.forEach { it.inject(Unit, mutableMapOf()) }
|
|
||||||
contextHolder.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ───────────────────────────────────────────────────────────────
|
|
||||||
6️⃣ WebClient 过滤器
|
|
||||||
─────────────────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置类,注册 WebClient 自定义器以支持上下文传播。
|
|
||||||
*/
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ConditionalOnClass(name = ["org.springframework.web.reactive.function.client.WebClient"])
|
|
||||||
class WebClientPart(private val registry: FieldRegistry) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册 WebClientCustomizer,用于定制 WebClient 的请求行为。
|
|
||||||
*
|
|
||||||
* 在每次请求发出前,将当前上下文字段写入 HTTP 请求头。
|
|
||||||
*@param contextHolder 上下文持有者
|
|
||||||
* @return 构建完成的 WebClientCustomizer 实例
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
fun contextWebClientCustomizer(contextHolder: ContextHolder) = WebClientCustomizer { builder ->
|
|
||||||
builder.filter { req, next ->
|
|
||||||
val ctx = contextHolder.snapshot()
|
|
||||||
val mutated = ClientRequest.from(req).apply {
|
|
||||||
registry.all().forEach { def ->
|
|
||||||
ctx[def.key]?.let { value -> header(def.header, value) }
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
next.exchange(mutated)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1 +1,8 @@
|
|||||||
com.gewuyou.forgeboot.context.autoconfigure.ForgeContextAutoConfiguration
|
com.gewuyou.forgeboot.context.autoconfigure.ContextCommonAutoConfiguration
|
||||||
|
com.gewuyou.forgeboot.context.autoconfigure.ContextProcessorAutoConfiguration
|
||||||
|
com.gewuyou.forgeboot.context.autoconfigure.ContextReactorAutoConfiguration
|
||||||
|
com.gewuyou.forgeboot.context.autoconfigure.ContextServletAutoConfiguration
|
||||||
|
com.gewuyou.forgeboot.context.autoconfigure.ContextWebFluxAutoConfiguration
|
||||||
|
com.gewuyou.forgeboot.context.autoconfigure.ContextFeignAutoConfiguration
|
||||||
|
com.gewuyou.forgeboot.context.autoconfigure.ContextTaskDecoratorAutoConfiguration
|
||||||
|
com.gewuyou.forgeboot.context.autoconfigure.ContextWebClientAutoConfiguration
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user