<Boolean> 如何在 if else 条件语句中使用 Mono?



我在反应式中使用Flux<Document>,以使我的休息服务是反应式的。我返回ResponseEntity<Flux<Document>>作为对我的休息服务的回应。现在我的服务总是返回HttpStatus.ok(),但我想增强它以在找不到内容的情况下返回HttpStatus.noContent()。 为了实现这一点,我试图检查 Flux 的大小。我发现这可以通过.count().hasElements()来实现.

如果我考虑.hasElements()那么它会返回Mono<Boolean>. 作为一个新手,我试图理解我如何使用它来做出HttpStatus.ok()HttpStatus.noContent()之间的决定。

这也是在反应中使用条件语句的正确方法,还是有任何其他方法可以实现它。

请您帮忙。

所以这是我为完成上述问题所做的:

final Flux<Document> returnDoc = <Reference of what I received from the Service layer>;
return returnDoc.hasElements()
.map(isNotEmpty -> {
if (isNotEmpty) 
return ResponseEntity.ok().body(returnDoc);
else {
return ResponseEntity.noContent().build();
}
});

这对我有用。让我知道是否有任何其他更好的解决方案。

反应式条件的诀窍是利用几个运算符来实现if / else行为。

多年来,我从使用 Webflux 中学到的一些运算符:

  • filter():通过某些谓词过滤流(例如if (2 > 1))
  • map():如果filter()发出true则将响应映射到某种类型
  • flatMap():将响应映射到Publisher(即Mono/Flux)
  • switchIfEmpty():如果发出filter()则发出默认Publisherfalse
  • defaultIfEmpty()发出默认类型

我将分享我的 redisson cache 和 r2dbc 代码作为示例。

下面是伪代码中的场景:

If a key is found in cache
return value
Else 
call database
set key & value pair in cache
return value

在任一情况下,值都包装到由状态和正文区分的ResponseEntity中。

@Override
public Mono<ResponseEntity<Res<UserSettings>>> getUserSetting(String username) {
Mono<UserSettings> queryAndSet =
userSettingsRepository
.findByUsername(username)
.flatMap(v1 -> cacheRepository.set("user_settings", username, v1).thenReturn(v1));
return cacheRepository
.get("user_settings", username, new TypeReference<UserSettings>() {}) // if then
.switchIfEmpty(queryAndSet) // else
.map(ResponseUtil::success) // if then
.defaultIfEmpty(singleError(UserMsg.USER_SETTINGS_NOT_FOUND.getCode())) // else
.map(v1 -> ResponseEntity.status(elseNotFound(v1)).body(v1)); // finally
}      

CacheRepository接口规格:

public interface CacheRepository {
Mono<Void> set(String table, String key, Object value);
Mono<Void> set(String table, String key, Object value, Long ttl, TimeUnit timeUnit);
<T> Mono<T> get(String table, String key, TypeReference<T> type);
Mono<Boolean> delete(String table, String key);
}

ResponseUtil有助于ResponseEntity包装器:

public class ResponseUtil {
private ResponseUtil() {}
public static <T> Response<T> success(T data) {
return Response.<T>builder().success(true).data(data).build();
}
public static <T> Response<T> singleError(String error) {
return Response.<T>builder().success(false).errors(List.of(error)).build();
}
public static <T> Response<T> multipleErrors(List<String> errors) {
return Response.<T>builder().success(false).errors(errors).build();
}
public static HttpStatus elseBadRequest(Response<?> res) {
return Boolean.TRUE.equals(res.isSuccess()) ? HttpStatus.OK : HttpStatus.BAD_REQUEST;
}
public static HttpStatus elseNotFound(Response<?> res) {
return Boolean.TRUE.equals(res.isSuccess()) ? HttpStatus.OK : HttpStatus.NOT_FOUND;
}
}

Response

// Idiotic wrapper
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Response<T> {
private T data;
private boolean success;
private List<String> errors;
}

最新更新