refactor(context): 将 ForgeContextAutoConfiguration 拆分为多个自动配置类

- 新增 ContextCommonAutoConfiguration、ContextProcessorAutoConfiguration、ContextReactorAutoConfiguration、ContextServletAutoConfiguration、ContextWebFluxAutoConfiguration、ContextFeignAutoConfiguration、ContextTaskDecoratorAutoConfiguration 和 ContextWebClientAutoConfiguration
- 删除 ForgeContextAutoConfiguration 类
- 更新 AutoConfiguration.imports 文件,添加新的自动配置类
This commit is contained in:
gewuyou 2025-06-24 22:41:03 +08:00
parent 9c11b7e2e5
commit 5f3ae7a5cd
10 changed files with 404 additions and 296 deletions

View File

@ -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())
}

View File

@ -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) }
}
}
}

View File

@ -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 根据字段定义生成默认值 traceIdspanId 适用于首次进入系统的情况
*
* @param reg 字段注册表用于获取需要生成值的上下文字段定义
* @return 构建完成的 GeneratorProcessor 实例
*/
@Bean("generatorProcessor")
fun generatorProcessor(reg: FieldRegistry): GeneratorProcessor {
return GeneratorProcessor(reg)
}
/**
* 创建 MdcProcessor Bean用于将上下文字段写入 MDCMapped Diagnostic Context
*
* MdcProcessor 使得日志框架 Logback可以访问当前上下文字段便于日志追踪
*
* @param reg 字段注册表用于获取需要写入 MDC 的上下文字段定义
* @return 构建完成的 MdcProcessor 实例
*/
@Bean("mdcProcessor")
fun mdcProcessor(reg: FieldRegistry): MdcProcessor {
return MdcProcessor(reg)
}
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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()
}
}
}
}

View File

@ -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) // 执行修改后的请求
}
}
}

View File

@ -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)
}

View File

@ -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 根据字段定义生成默认值 traceIdspanId 适用于首次进入系统的情况
*
* @param reg 字段注册表
* @return 构建完成的 GeneratorProcessor 实例
*/
@Bean("generatorProcessor")
fun generatorProcessor(reg: FieldRegistry) = GeneratorProcessor(reg)
/**
* 创建 MdcProcessor Bean用于将上下文字段写入 MDCMapped 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)
}
}
}
}

View File

@ -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