Webflux 将 Mono 的结果存储到会话变量

问题描述

我的 Spring Boot Webflux 应用程序 (Netty) 使用 Thymeleaf 模板输出 HTML。在一种处理程序方法中,我使用 WebClient 与外部 id 提供者进行身份验证。 现在我想将生成的身份验证令牌存储在会话变量中,以便我可以在后续的控制器/处理程序方法中重用它。 如果我将令牌存储在模型变量中,Spring/Webflux 在呈现之前解析 Mono 并提供结果令牌字符串以供视图(Thymeleaf 模板)使用。但是我找不到将令牌存储在会话变量中的方法。 WebSession 对我来说已经足够了,因为我不会运行具有多个节点的应用程序。

我尝试过的代码(Kotlin):

@PostMapping("/login")
fun login(@Valid loginForm: LoginForm,model: Model,webSession: WebSession): String {
  val tokenMono: Mono<String> = loginService.login(loginForm.email,loginForm.password)
  model.addAttribute("token",tokenMono) // works and the token is available as a String in resulting view template
  webSession.addAttribute("token",tokenMono) // session-variable "token" is null in subsequent requests.
  return "login/success"
}

解决方法

以下似乎有效:

@PostMapping("/login")
fun login(@Valid loginForm: LoginForm,webSession: WebSession): Mono<String> {
   return loginService.login(loginForm.email,loginForm.password)
     .doOnNext { token ->
        webSession.attributes["token"] = token
     }
     .map { token -> "login/success" }
}

主要学习:

  • 模板视图名称(此处为“login/success”)可以包含在 Mono 中。
  • 在检索反应式类型后需要完成的所有操作都需要包含在 Mono 的 onXXX 函数之一中(也许 then 也可以)。
  • 这也适用于重定向到需要响应式类型结果中的某些内容的处理程序方法。所以说原始 Mono 是 R2DB 插入的未来结果。如果我想重定向到结果视图,我可以使用 .map { entity -> "redirect:/entity/${entity.id}" }