首页 > 解决方案 > 如果 Flux 有异常,如何“窥视”?

问题描述

我将 Spring Webflux 与 Tomcat servlet 容器(spring-boot-starter-web + spring-boot-starter-webflux)一起使用,我想得到以下结果:

如果通量立即失败,我想发送给客户端响应代码 400

否则,我想发送响应代码 200 并流式传输通量

我尝试了不同的解决方案,但没有一个有效。v1并且v2如果失败场景不发送预期的响应代码,v3不流输出是快乐的场景。

我想在failFlux发送响应代码 200 之前“窥视”异常并触发异常

@RequestMapping(produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public class X {
 Flux<String> happyFlux = Flux.generate(s -> s.next("x"));  
 Flux<String> failFlux = Flux.error(new ResponseStatusException(BAD_REQUEST));

 //ok: flux is streamed

 @RequestMapping("/v1/happy")
 Flux<String> v1Happy() {
    return happyFlux;
 }

 //nok: http status code is 200

 @RequestMapping("/v1/fail")
 Flux<String> v1Fail() {
    return failFlux;
 }

 //ok: flux is streamed

 @RequestMapping("/v2/happy")
 Mono<ResponseEntity<Flux<String>>> v2Happy() {
    return Mono.just(ResponseEntity.ok().body(happyFlux));
 }

 //nok: http status code is 200

 @RequestMapping("/v2/fail")
 Mono<ResponseEntity<Flux<String>>> v2Fail() {
    return Mono.just(ResponseEntity.ok().body(failFlux));
 }

 //nok: flux is not streamed but collected on server side

 @RequestMapping("/v3/happy")
 Mono<ResponseEntity<List<String>>> v3Happy() {
    return happyFlux.collectList().map(ResponseEntity::ok);
 }

 //ok: http status code is 400

 @RequestMapping("/v3/fail")
 Mono<ResponseEntity<List<String>>> v3Fail() {
    return failFlux.collectList().map(ResponseEntity::ok);
 }

PS。有趣的是,v1可以v2与 netty 一起使用(仅spring-boot-starter-webflux)。

更新

我认为“偷窥” Flux 是不可能的。对于 servlet 堆栈,我真正在 Spring 中更好的 Flux 处理:https ://jira.spring.io/browse/SPR-17440

标签: spring-webfluxproject-reactor

解决方案


我建议不要使用 collectList() ,因为这会破坏生成 Stream 的全部目的。我相信如果出现异常消息,您应该得到 500。

例如,检查下面的代码。

public Mono<ServerResponse> listPeople(ServerRequest request) {
    int error = 10/0;
    Flux<Person> peopleFlux = this.repository.allPeople();
    peopleFlux = withDelay(peopleFlux);

    return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM).body(peopleFlux, Person.class);


}

该声明

int error = 10/0;

导致 500 异常,在客户端我得到 500。如果我注释掉错误语句,那么我得到 200。所以,如果你没有得到 500,请分享你的代码。请注意,如果错误发生在服务器之后开始在流中返回单个事件,那么它将不是 500。您应该使用 HTTP 207。https ://httpstatuses.com/207


推荐阅读