Gau*_*arg 4 spring-boot spring-webflux spring-webclient
我正在尝试使用 Spring WebFlux WebClient获取值(字符串) (使用 SpringBoot 版本 2.4.5)
\n@GetMapping("/test")\npublic Mono<String> getData(){\n WebClient webClient = WebClient.create("http://localhost:9999");\n Mono<String> stringMono = webClient.get()\n .uri("/some/thing")\n .retrieve()\n .bodyToMono(String.class);\n stringMono.subscribe( System.out::println);\n System.out.println("Value : " + stringMono.block()); // this doesn\'t work, expecting to return ResponseBody as "Hello World" ,\n return stringMono;\n}\nRun Code Online (Sandbox Code Playgroud)\n但低于错误
\n2021-05-11 20:02:15.521 ERROR 55613 --- [ctor-http-nio-2] a.w.r.e.AbstractErrorWebExceptionHandler : [19114471-1] 500 Server Error for HTTP GET "/test"\njava.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2\n at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83) ~[reactor-core-3.4.3.jar:3.4.3]\n Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: \nError has been observed at the following site(s):\n |_ checkpoint \xe2\x87\xa2 HTTP GET "/test" [ExceptionHandlingWebHandler]\nStack trace:\n at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83) ~[reactor-core-3.4.3.jar:3.4.3]\n at reactor.core.publisher.Mono.block(Mono.java:1703) ~[reactor-core-3.4.3.jar:3.4.3]\n at com.example.demo.DemoApplication.getData(DemoApplication.java:28) ~[main/:na]\n at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]\n at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]\n at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]\n at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]\n at org.springframework.web.reactive.result.method.InvocableHandlerMethod.lambda$invoke$0(InvocableHandlerMethod.java:146) ~[spring-webflux-5.3.4.jar:5.3.4]\n at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:151) ~[reactor-core-3.4.3.jar:3.4.3]\nRun Code Online (Sandbox Code Playgroud)\n\n
使用 Webflux 时,整个想法是您不要阻止 - 如果您这样做,您将导致巨大的性能问题(请参阅此处的相关答案来解释原因),因此框架明确不允许它,如果您尝试,则会抛出异常。
您也不应该手动订阅 - 虽然在响应式世界中不像阻塞那样是“死罪”,但这肯定是另一个危险信号。订阅由框架处理。您只需要返回Mono,Webflux 就会在需要时订阅来处理您的请求。在您的情况下,您的手动订阅意味着整个链实际上将为每个请求执行两次- 一次将结果打印到终端,一次将结果返回到端点/test。
相反,如果您想要像这样的“副作用”(当您拥有值时打印出该值),那么您需要使用doOnNext()运算符更改反应链来执行此操作。这意味着您可以执行以下操作:
return webClient.get()
.uri("/some/thing")
.retrieve()
.bodyToMono(String.class)
.doOnNext(s -> System.out.println("Value: " + s));
Run Code Online (Sandbox Code Playgroud)
这将确保将值打印到终端,但不会阻塞,也无需手动订阅。
| 归档时间: |
|
| 查看次数: |
14452 次 |
| 最近记录: |