Spring WebFlux中等同SessionLocaleResolver的响应式会话区域解析实现问询
可行解决方案
方案1:WebFilter前置解析会话Locale,存入Exchange属性
这是目前兼容性最好的落地方案,核心思路是在请求进入LocaleContextResolver之前,就通过WebFilter异步获取会话数据,将解析完成的Locale存入ServerWebExchange的属性中,后续LocaleContextResolver仅需要同步从属性取值即可,完全不需要调用block()阻塞线程。
示例实现代码如下:
- 前置解析WebFilter
@Component class SessionLocalePreParseFilter : WebFilter { override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> { return exchange.session .map { webSession -> // 从会话中读取提前存储的用户Locale值 val sessionLocale = webSession.getAttribute<Locale>("USER_LOCALE") // 存入Exchange属性供后续解析器读取 exchange.attributes["parsed_locale"] = sessionLocale ?: Locale.forLanguageTag("en-US") exchange } .flatMap { chain.filter(it) } } }
- 自定义
LocaleContextResolver
class SessionLocaleContextResolver : LocaleContextResolver { override fun resolveLocaleContext(exchange: ServerWebExchange): LocaleContext { // 直接从属性同步取值,无任何阻塞操作 val locale = exchange.attributes["parsed_locale"] as Locale return SimpleLocaleContext(locale) } override fun setLocaleContext(exchange: ServerWebExchange, localeContext: LocaleContext?) { // 异步实现Locale存入会话的逻辑,完全符合响应式规范 exchange.session.subscribe { webSession -> webSession.attributes["USER_LOCALE"] = localeContext?.locale } } }
该方案完全兼容Spring WebFlux原生i18n体系,不需要修改其他依赖Locale的内置组件,性能符合响应式编程规范。
方案2:绕过原生解析器,直接通过Reactor Context传递Locale
如果你的应用不需要兼容Spring自带的i18n组件,也可以直接将解析完成的Locale存入Reactor的上下文,在需要国际化的业务位置主动读取即可:
- 上下文注入Filter
@Component class LocaleContextFilter : WebFilter { override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> { return exchange.session .map { it.getAttribute<Locale>("USER_LOCALE") ?: Locale.US } .flatMap { locale -> chain.filter(exchange) .contextWrite(Context.of("REQUEST_LOCALE", locale)) } } }
- 业务层读取Locale
fun getI18nMessage(code: String): Mono<String> { return Mono.deferContextual { ctx -> val locale = ctx.get<Locale>("REQUEST_LOCALE") Mono.just(messageSource.getMessage(code, null, locale)) } }
官方接口调整规划
目前Spring官方社区已经收到了大量关于响应式LocaleContextResolver需要支持异步解析的反馈,相关功能提案已经进入Spring Framework的需求队列,不过截至Spring Framework 6.1版本,还没有正式落地异步版本的区域解析接口。官方倾向于在后续大版本迭代中补充响应式专属的区域解析接口,在此之前推荐使用上述WebFilter前置处理方案作为兼容实现。
内容的提问来源于stack exchange,提问作者Arie Xiao
相关产品推荐
相关产品推荐

