![](/img/trans.png)
[英]Get body to flux if I have list of strings in server request body and iterate over them
[英]Can I have Flux as a field of ServerResponse body?
我是 Spring Reactive Web 的新手,我遇到了以下问题。 我想创建一个带有接受数字 N 的端点的微服务 A,向微服务 B 发送 N 个请求(它为每个请求返回一个字符串),将字符串包装成对象,将它们组合成 List/Flux(?)并返回带有这些对象的 JSON,例如:
{
"number": 4,
"objects": [
{
"name": "first"
},
{
"name": "second"
},
{
"name": "third"
},
{
"name": "fourth"
}
]
}
我想为此使用功能端点。 所以我尝试了以下方法(尽我所能简化它):
public class MyObject {
private String name; // here should be a value received from B
// ...
}
public class MyResponse {
private int number;
private Flux<MyObject> objects; // or List?
// ...
}
@Component
@RequiredArgsConstructor
public class MyHandler {
private final MyClient client;
public Mono<ServerResponse> generate(ServerRequest serverRequest) {
return serverRequest.bodyToMono(MyRequestBody.class)
.flatMap(request -> buildServerResponse(HttpStatus.OK, buildResponseBody(request)));
}
private Mono<ServerResponse> buildServerResponse(HttpStatus status, Mono<MyResponse> responseBody) {
return ServerResponse.status(status)
.contentType(MediaType.APPLICATION_JSON)
.body(responseBody, MyResponse.class);
}
private Mono<MyResponse> buildResponseBody(MyRequestBody request) {
return Mono.just(MyResponse.builder()
.number(request.getNumber())
.objects(getObjects(request.getNumber())
.build());
}
private Flux<MyObject> getObjects(int n) {
// how to receive n strings from MyClient, make MyObject from each of them and then combine them together to a Flux/List?
}
public class MyClient {
public Mono<String> getName() {
WebClient client = WebClient.builder().baseUrl(getUrl()).build();
return client.get()
// ...
.retrieve()
.bodyToMono(String.class);
}
private String getUrl() {
// ...
}
}
所以,如果我在 MyResponse 中使用 Flux,我会收到如下响应:
{
"number": 4,
"objects": {
"prefetch": 2147483647,
"scanAvailable": true
}
}
另一方面,如果我尝试使用列表,它似乎需要在某些时候阻塞,并且我收到与之相关的错误。 那么,我该怎么做呢?
提前致谢!
更新:如果我使用collectList().block()
从 Flux 中创建一个列表,我会收到以下信息:
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread <...>
正如我从这个问题的答案中了解到的那样,当我的方法返回Mono
/ Flux
时,我永远不应该阻止。 将block()
调用提取到从返回Mono
/ Flux
的方法调用的单独方法没有帮助。 如果我在block()
share()
) ,那么我的请求将永远执行,出于某种我还不明白的原因。
好吧,我做到了。
Flux
作为一个字段不能以期望的方式工作,所以我需要一个List
。
public class MyResponse {
private int number;
private List<MyObject> objects;
// ...
}
现在我需要一种方法从多个Mono<String>
中创建一个List<MyObject>
,其中每个MyObject
都有一个String
字段。
问题是我们永远不会摆脱Mono
或Flux
,所以我们首先为Flux<MyObject>
删除 go 。
private Flux<MyObject> getObjects(int n) {
return Flux.range(0, n) // Flux<Integer>
.map(i -> myClient.getName()) // Flux<String>
.map(name -> new MyObject(name)); // Flux<MyObject>
}
然后我们制作通量:
private Mono<MyResponse> buildResponseBody(MyRequestBody request) {
return getObjects(request.getNumber()) // Flux<MyObject>
.collectList() // Mono<List<MyObject>>
.map(objects -> MyResponse.builder() // Mono<MyResponse>
.number(request.getNumber())
.objects(objects)
.build()));
}
这样它就可以工作,因为我们不必阻止任何东西。
只有当我们想在某个时候摆脱Mono
/ Flux
时,问题才会出现,就像我们想要一个纯List<MyObject>
一样。 但只要我们有Mono
和/或Flux
作为输入和 output,我们就可以使用这些类的方法进行所有操作,在每个阶段保留Mono
或Flux
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.