当前位置: 首页 > 知识库问答 >
问题:

我可以将Flux作为ServerResponse主体的字段吗?

房项禹
2023-03-14

我是Spring Reactive Web的新手,我遇到了以下问题。我想创建一个微服务A,它的endpoint接受一个数字N,向微服务B发送N个请求(微服务B为每个请求返回一个字符串),将字符串包装成对象,将它们组合成一个List/Flux(?)并返回带有这些对象的JSON,比如:

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

我想为此使用一个功能endpoint。所以我尝试了以下方法(尽量简化):

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

所以,如果我在我的响应中使用Flux,我会收到这样的响应:

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

另一方面,如果我尝试使用一个List,它似乎需要在某个时刻阻塞,并且我会收到与它相关的错误。那么,我该怎么做呢?

提前感谢!

更新:如果我使用CollectList(). block()从Flux制作一个列表,我会收到这个:

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

正如我从这个问题的答案中了解到的,当我的方法返回Mono/Flux时,我不应该阻塞。将block()调用从返回Mono/Flux的方法中调用的单独方法例外是没有帮助的。如果我在block()之前使用share(),那么我的请求就会永远执行,出于某种我还不明白的原因。

共有1个答案

齐泰
2023-03-14

好吧,我成功了。

<code>Flux</code>作为一个字段不能以期望的方式工作,所以我需要一个<code<List>/code。

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

现在我需要一个方法来制作一个列表。

问题是,我们永远不会摆脱单晶助焊剂,所以我们选择助焊剂。

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时,才会出现问题,比如我们想要一个纯列表

 类似资料:
  • 问题内容: 我有一个用于存储优惠券/折扣的表,并且我想将coupon_code列用作主键,即。 我的理由是,每个优惠券都将具有唯一的代码,而我将要运行的唯一命令是 我不会进行任何联接或索引编制,并且我看不到该表中有超过几百个条目。 在我看来,这可以,但是我不知道是否有任何我想念的东西。 问题答案: 从某种意义上说,您当然可以,您的RDBMS将允许您这样做。这个问题的答案,你是否没有问题 应该 做到

  • 通过阅读本文,我发现HTML5中引入了一些“有效”和“无效”输入值的伪类。 有没有办法从javascript中将输入字段标记为无效/有效?或者,我可以替代使用的验证方法吗?

  • 我已经开始使用Spring WebFlux,最近我想知道为什么ServerResponse没有主体类型的泛型。这与同步响应不一致 ServerResponse中的响应体类型在此方法的签名中未知。是不是应该像下面这样? 我想知道ServerResponse没有这种泛型类型的原因是什么?

  • 我正在使用TypeORM从Rails迁移到NestJs。由于历史的原因,Rails中的表名和列名都是——我不想把这个讨厌的东西复制到我们的NestJs/React端。 是否可以在NestJS(typeorm)中创建名为但映射到DB中名为的列的实体字段? 我的桌子 我的用户实体类

  • 问题内容: 我有这个代码 我不一定总拥有三个书本价值。所以有时候,如果我不知道主题,位置或出版商。那我要让他们空着 但是如果有的话,我需要选择框进行选择。这样有可能吗 问题答案: 当然,只需为要保留为可选的每个字段添加即可

  • 我有两张桌子: 用户(用户名、密码) 配置文件(profileId,gender,dateofbirding,...) 目前我正在使用这种方法:每个Profile记录都有一个名为“userid”的字段作为外键,它链接到用户表。当用户注册时,他的配置文件记录将自动创建。 我对我朋友的建议感到困惑:将“userid”字段作为外部和主键,并删除“profileid”字段。哪种方法更好?