Return 404 当 Flux 为空时

Return 404 when a Flux is empty

我正在尝试 return 当 Flux 为空时的 404,类似于此处:

我主要担心的是,当你检查助焊剂是否有元素时,它会发出那个值,然后你就失去了它。当我尝试在服务器响应上使用 switch if empty 时,它永远不会被调用(我暗自认为这是因为 Mono 不为空,只有 body 为空)。

我正在做的一些代码(我的路由器上确实有一个过滤器 class 检查 DataNotFoundException 到 return notFound):

Flux<Location> response = this.locationService.searchLocations(searchFields, pageToken);
return ok()
        .contentType(APPLICATION_STREAM_JSON)
        .body(response, Location.class)
        .switchIfEmpty(Mono.error(new DataNotFoundException("The data you seek is not here.")));

^这从不调用 switchIfEmpty

Flux<Location> response = this.locationService.searchLocations(searchFields, pageToken);

return response.hasElements().flatMap(l ->{
   if(l){
       return ok()
               .contentType(APPLICATION_STREAM_JSON)
               .body(response, Location.class);
   } 
   else{
       return Mono.error(new DataNotFoundException("The data you seek is not here."));
   }
});

^这会丢失 hasElements 上发出的元素。

有没有办法在 hasElements 中恢复发出的元素,或者让 switchIfEmpty 只检查正文的内容?

您可以将 switchIfEmpty 运算符应用于您的 Flux<Location> response

Flux<Location> response = this.locationService
        .searchLocations(searchFields, pageToken)
        .switchIfEmpty(Mono.error(new DataNotFoundException("The data you seek is not here.")));

亚历山大写的是正确的。您在从不为空的对象上调用 switchIfEmpty 根据定义,ServerResponse.ok() 不是空的发布者。我喜欢反向处理这种情况,因此调用服务然后链接创建响应的所有方法。

    this.locationService.searchLocations(searchFields, pageToken)
            .buffer()
            .map(t -> ResponseEntity.ok(t))
            .defaultIfEmpty(ResponseEntity.notFound().build());

更新(不确定是否有效,但试一试):

 public Mono<ServerResponse> myRestMethod(ServerRequest serverRequest) {
        return serverRequest.bodyToMono(RequestDTO.class)
                .map((request) -> searchLocations(request.searchFields, request.pageToken))
                .flatMap( t -> ServerResponse
                        .ok()
                        .body(t, ResponseDTO.class)
                )
                .switchIfEmpty(ServerResponse.notFound().build())
                ;
    }

虽然发布的答案确实正确,但如果您只想 return 状态代码(加上原因)而不想 fiddle,则有一个方便的例外 class ] 使用任何自定义过滤器或定义您自己的错误响应异常。

另一个好处是您不必将响应包装在任何 ResponseEntity 对象中,虽然在某些情况下很有用(例如,使用位置 URI 创建),但对于简单的状态响应来说有点矫枉过正。

另见 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/ResponseStatusException.html

 return this.locationService.searchLocations(searchFields, pageToken)
        .buffer()
        .switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.NOT_FOUND, "these are not the droids you are lookig for")));