为什么当调用 .block() 时,反应堆上下文抛出"Context does not contain key"?



我有一个WebFilter,它注入了一个上下文

public class MyWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange)
.contextWrite(ctx -> ctx.put("context", "some-context"));
}
}

在我的控制器中,我可以读取并成功返回

@RestController
public class MyController {
@GetMapping(path = "test")
public Mono<String> test() {
return Mono.deferContextual(ctx -> Mono.just(ctx.get("context")));
}
}

但是,如果我在上面调用.block()

Mono.deferContextual(ctx -> Mono.just(ctx.get("context"))).block();

它抛出这个异常

java.util.NoSuchElementException:上下文不包含关键字:上下文

在被动世界中,我很难理解执行顺序。

当您调用.block((时,会立即订阅并评估该行,而不会与外链中提供的上下文有任何连接。当您返回时不带.block,它将成为具有上下文的较大链的一部分,并且在某个东西订阅了上下文可用的外部链之前不会进行评估。

您将希望Spring尽可能"现实地"处理此问题。创建一个测试并使用WebTestClient。(永远不要调用.block(),否则你的服务器会被六个用户拒绝。不要直接注入/调用你的控制器方法,你需要所有的代理、过滤器等。(

这是kotlin,但你应该能够弄清楚:

@SpringBootApplication
class WebfluxScratchpadApplication {
@Bean
fun filter(): WebFilter = WebFilter { serverWebExchange, webFilterChain ->
webFilterChain.filter(serverWebExchange)
.contextWrite {
it.put("myContextKey", "!!")
}
}
}
@RestController
class MyController {
@GetMapping("/foo")
fun foo() = Mono.just("foo")
.flatMap { s ->
Mono.deferContextual { ctx ->
Mono.just(String.format("%s%s", s, ctx["myContextKey"]))
}
}
}
fun main(args: Array<String>) {
runApplication<WebfluxScratchpadApplication>(*args)
}
@WebFluxTest
class WebfluxScratchpadApplicationTests {
@Autowired
lateinit var client: WebTestClient
@Test
fun stuff() {
Assertions.assertEquals(
"foo!!",
client.get()
.uri("/foo")
.exchange()
.expectBody<String>()
.returnResult()
.responseBody!!
)
}
}

相关内容

最新更新