【问题标题】:Writing 'reactive' WebFlux controller编写“反应式”WebFlux 控制器
【发布时间】:2020-12-25 15:36:58
【问题描述】:

我正在尝试将 WebMVC 控制器转换为返回 Mono<Resource> 的 WebFlux 控制器。

旧的WebMVC 控制器如下所示。

@GetMapping("/resources/{id}")
public ResponseEntity<Resource> getCustomer(@RequestParam String id) {
    if(id.length != 10) {
        // set ResponseEntity status 400 and then return it
    }

    val resource = resourceService.getResourceById(id);    
    return ResponseEntity.ok().body(resource);
}

如何让if 块与Reactive Programming 更兼容?

【问题讨论】:

  • 你试过什么?
  • 我试过 if ... else ... 就像@nipuna-saranga 在下面的回答,但无法确定这种代码在反应式编程方面是否正确。
  • 他提供了一个很好的答案。

标签: java spring-webflux


【解决方案1】:

如果您使用的是函数式端点,您可以执行类似的操作。

public Mono<ServerResponse> getCustomer(ServerRequest serverRequest) {

  if (serverRequest.pathVariable("id").length() != 10) {

    return ServerResponse
        .status(400)
        .build();

  } else {

    return ServerResponse
        .ok()
        .body(
            resourceService.getResourceById(serverRequest.pathVariable("id")),
            Resource.class
        );

  }

}

上面提到的对我来说更具可读性。但是如果你真的想在方法中维护流,你可以从Mono.just(serverRequest.pathVariable("id"))开始,如下所示。

return Mono.just(serverRequest.pathVariable("id"))
  .filter(id -> id.length() == 10)
  .flatMap(resourceService::getResourceById)
  .flatMap(resource -> ServerResponse
      .ok()
      .body(
          resourceService.getResourceById(serverRequest.pathVariable("id")),
          Resource.class
      )
  )
  .switchIfEmpty(ServerResponse.status(400).build());

类似地,如果您使用带注释的控制器,类似下面的内容似乎更具可读性(对我来说 :))。

@GetMapping(path = "/resources/{id}")
public ResponseEntity<Mono<Resource>> getCustomer(@PathVariable String id) {

  if (id.length() != 10) {

    return ResponseEntity
            .status(400)
            .build();

  } else {

    return ResponseEntity
        .ok()
        .body(resourceService
            .getResourceById(id));

  }

}

官方文档是一个足够好的参考: 文档中的两个相关部分

  1. https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-controller
  2. https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-fn

【讨论】:

  • 我不认为 ResponseEntity> 是被动的。而 Mono> 是反应式的
  • @PatPatPat 我想知道同样的一段时间,你有参考吗?我找不到任何确定的东西。我在代码示例和教程中都看到了这两种方式。我看到一个与你名字相似的人发布的 github issue 已关闭,是你吗?但这也没有给出明确的答案。
【解决方案2】:

你需要为webflux功能流程创建handler、router

@Component

公共类 SampleHandlerFunction {

public Mono<ServerResponse> flux(ServerRequest serverRequest) {

    return ServerResponse.ok()
            .contentType(MediaType.APPLICATION_JSON)
            .body(
                    Flux.just(1, 2, 3, 4)
                            .log(), Integer.class
            );
}

public Mono<ServerResponse> mono(ServerRequest serverRequest) {

    return ServerResponse.ok()
            .contentType(MediaType.APPLICATION_JSON)
            .body(
                    Mono.just(1)
                            .log(), Integer.class
            );
}

路由器

@Configuration

公共类RouterFunctionConfig {

@Bean
public RouterFunction<ServerResponse> route(com.Reactive.SpringReactive.handler.SampleHandlerFunction handlerFunction){

    return RouterFunctions
            .route(GET("/functional/flux").and(accept(MediaType.APPLICATION_JSON)),handlerFunction::flux)
            .andRoute(GET("/functional/mono").and(accept(MediaType.APPLICATION_JSON)),handlerFunction::mono);

}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-29
    • 2018-02-08
    • 2021-12-12
    • 2020-04-05
    • 2021-11-18
    • 2018-06-24
    • 2021-04-12
    • 1970-01-01
    相关资源
    最近更新 更多