简体   繁体   English

我可以将 Flux 作为 ServerResponse 正文的一个字段吗?

[英]Can I have Flux as a field of ServerResponse body?

I'm new to Spring Reactive Web, and i met the following issue.我是 Spring Reactive Web 的新手,我遇到了以下问题。 I want to create a microservice A with an endpoint which accepts a number N, sends N requests to microservice B (which returns a string for each request), wraps the strings into objects, combines them into a List/Flux (?) and returns a JSON with those objects, like:我想创建一个带有接受数字 N 的端点的微服务 A,向微服务 B 发送 N 个请求(它为每个请求返回一个字符串),将字符串包装成对象,将它们组合成 List/Flux(?)并返回带有这些对象的 JSON,例如:

{
  "number": 4,
  "objects": [
    {
       "name": "first"
    },
    {
       "name": "second"
    },
    {
       "name": "third"
    },
    {
       "name": "fourth"
    }
  ]
}

I want to use a functional endpoint for this.我想为此使用功能端点。 So i tried the following (made my best to simplify it):所以我尝试了以下方法(尽我所能简化它):

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() {
        // ...
    }
}

So, if i use Flux in MyResponse, i receive a response like:所以,如果我在 MyResponse 中使用 Flux,我会收到如下响应:

{
  "number": 4,
  "objects": {
    "prefetch": 2147483647,
    "scanAvailable": true
  }
}

on the other hand, if i try to use a List, it seems to require blocking at some point, and i receive errors related to it.另一方面,如果我尝试使用列表,它似乎需要在某些时候阻塞,并且我收到与之相关的错误。 So, how do i do it?那么,我该怎么做呢?

Thanks in advance!提前致谢!


UPDATE: if i use collectList().block() to make a List out of Flux, i receive this:更新:如果我使用collectList().block()从 Flux 中创建一个列表,我会收到以下信息:

java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread <...>

As I understand from answers to this question, i should never block when my method returns Mono / Flux .正如我从这个问题的答案中了解到的那样,当我的方法返回Mono / Flux时,我永远不应该阻止。 Exctracting the block() call to a separate method which is called from the one returning Mono / Flux doesn't help.block()调用提取到从返回Mono / Flux的方法调用的单独方法没有帮助。 If i use share() before block() , then my request just executes forever, for some reason which i don't understand yet.如果我在block() share() ) ,那么我的请求将永远执行,出于某种我还不明白的原因。

Alright, i made it.好吧,我做到了。

Flux as a field doesn't work in a desired way, so i need a List . Flux作为一个字段不能以期望的方式工作,所以我需要一个List

public class MyResponse {
    private int number;
    private List<MyObject> objects;
    // ...
}

Now i need a way to make a List<MyObject> out of multiple Mono<String> s where each MyObject has a String field.现在我需要一种方法从多个Mono<String>中创建一个List<MyObject> ,其中每个MyObject都有一个String字段。

The thing is that we don't ever get rid out of Mono or Flux , so we go for Flux<MyObject> first.问题是我们永远不会摆脱MonoFlux ,所以我们首先为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>
}

and then we make Flux:然后我们制作通量:

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()));
}

This way it works, as we don't have to block anything.这样它就可以工作,因为我们不必阻止任何东西。

The problem only appears when we want to get rid of Mono / Flux at some point, like if we want a pure List<MyObject> .只有当我们想在某个时候摆脱Mono / Flux时,问题才会出现,就像我们想要一个纯List<MyObject>一样。 But as long as we have a Mono and/or Flux as both input and output, we can do all the manipulations with the methods of these classes, preserving Mono or Flux at each stage.但只要我们有Mono和/或Flux作为输入和 output,我们就可以使用这些类的方法进行所有操作,在每个阶段保留MonoFlux

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果我在服务器请求主体中有字符串列表并迭代它们,请获取通量 - Get body to flux if I have list of strings in server request body and iterate over them 在 Flux.error 的情况下返回相关的 ServerResponse - Return relevant ServerResponse in case of Flux.error 我可以在API中包含文件和请求正文吗 - Can I have file and request body in an API 为什么要通过 Mono<ServerResponse> 来自 webflux 路由器中的处理程序函数而不是 Flux<ServerResponse> - Why pass Mono<ServerResponse> from handler function in webflux router and not Flux<ServerResponse> 如何从 ServerResponse 获取 body 作为 String 进行测试? - How to get body as String from ServerResponse for test? Spring Webflux 中的模拟 flatMap ServerResponse 主体 - Mock flatMap ServerResponse Body in Spring Webflux 我可以在 Flux.generate 状态生成器中阻止远程调用吗 - Can I have blocking remote call in Flux.generate state generator 我可以在@Document中具有Class类型的字段吗? - Can I have a field in a @Document that is of the Class type? 在ormlite中,我如何拥有前字段和字段列? - In ormlite, How can I have a foriegn field and a field column? 接口方法可以有主体吗? - Can an interface method have a body?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM