如何从 WebFilter 中的 Mono 有条件地 return?

How do I conditionally return from a Mono within a WebFilter?

不确定我问的是否正确,所以这是我想做的事情的示例(命令式阻塞)

public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
  Mono<MyThing> myThingMono = getMyThingMono();
  // I Know this is not right but it's effectively what I want to do
  if( myThingMono is empty ) {
    return chain.filter(exchange);
  } else {
    MyThing thing = myThingMono.block(); // I know I can't do this
    switch(thing.status) {
      case A:
        exchange.getResponse().setStatus(HttpStatus.BAD_REQUEST);
        return exchange.getResponse().setComplete();
      default: 
        return chain.filter(exchange);
    }
  }
}

这是我以反应方式获得的最接近的结果

public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
  Mono<MyThing> myThingMono = getMyThingMono();
  myThingMono.map(thing -> {
    switch(thing.status) {
      case A: return HttpStatus.BAD_REQUEST;
      default: return HttpStatus.OK;
    }        
  })
  .defaultIfEmpty(HttpStatus.OK) // in case myThingMono is empty
  .map(status -> {
    switch(status) {
      case HttpStatus.OK:
        return chain.filter(exchange);
      default:
        exchange.getResponse().setStatusCode(status);
        return exchange.getResponse().setComplete();
    }        
  })
  .then();

myThingMono 想要 return 一个 Mono<Object>,但我的过滤器需要一个 Mono<Void>,所以我只是将一个 .then() 塞进了它。我确定那是不对的。

我的代码编译并到达最终的 switch 语句并调用正确的 return 语句,但请求没有到达我的控制器。 Web 过滤器未正确转发请求。我只是在没有处理程序结果的情况下返回 200 状态。

执行此操作的正确反应方式是什么?

我的意思是这样的。如果您的代码没有在第一次转换时输入,我使用 .switchIfEmpty(Mono.empty()) 到 return 的东西。您还可以创建默认 Mono.just(new MyThing()).

然后我使用 flatMap 将所有逻辑 switch ... 放入其中。

enum MyThingEnum { A }

class MyThing { public MyThingEnum status; }

public class Test {
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        Mono<MyThing> myThingMono = getMyThingMono();
        return myThingMono.flatMap(thing -> {
            switch (thing.status) {
                case A:
                    exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
                    return exchange.getResponse().setComplete();
                default:
                    exchange.getResponse().setStatusCode(HttpStatus.OK);
                    return chain.filter(exchange);
            }
        })
        .switchIfEmpty(Mono.empty());
    }

    private Mono<MyThing> getMyThingMono() {
        return Mono.just(new MyThing());
    }
}