【问题标题】:How do I conditionally return from a Mono within a WebFilter?如何有条件地从 WebFilter 中的 Mono 返回?
【发布时间】:2021-06-22 20:14:54
【问题描述】:

不知道我问的对不对,所以这里有一个我想做的例子(以命令式的阻塞方式)

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 想要返回一个Mono&lt;Object&gt;,但我的过滤器期待一个Mono&lt;Void&gt;,所以我只是将.then() 塞入其中。我确定这是不对的。

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

什么是正确的反应方式?

【问题讨论】:

  • 将第二张地图的代码放在第一张地图中,去掉.then()
  • 如果一切都在第一张地图中,如果myThingMono 为空会发生什么?第一个地图功能将被完全跳过。另外,我认为问题在于地图内的return 函数没有转发请求。也许我不完全理解该提案,所以如果您可以在答案中提供一些代码,它可能会有所帮助

标签: java spring-boot reactive-programming spring-webflux project-reactor


【解决方案1】:

我的意思是这样的。如果您的代码在第一次转换时没有输入,我使用.switchIfEmpty(Mono.empty()) 返回一些东西。您也可以创建一个默认的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());
    }
}

【讨论】:

  • 不幸的是,这行不通。我的核心问题是即使我返回了正确的东西,请求流也会中断。在您的解决方案中,switchIfEmpty(Mono.empty()) 肯定会中断请求流并阻止请求到达控制器,这是我要解决的主要问题。
  • 其实这个例子提供了解决方案的关键。我使用的是.map(),而我本应使用.flatMap(),如本例所示。
猜你喜欢
  • 1970-01-01
  • 2021-06-23
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
  • 2018-04-19
  • 2021-09-09
  • 1970-01-01
  • 2020-08-19
相关资源
最近更新 更多