【问题标题】:How to use Mono<Boolean> in if else conditional statement?如何在 if else 条件语句中使用 Mono<Boolean>?
【发布时间】:2023-02-18 02:44:46
【问题描述】:

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

如果我考虑.hasElements(),那么它会返回Mono&lt;Boolean&gt;。 作为新手,我试图理解如何使用它在HttpStatus.ok()HttpStatus.noContent() 之间做出决定。

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

请求您的帮助。

【问题讨论】:

  • 请将您的代码添加到问题中而不是描述它。谢谢!

标签: java spring-boot reactive-programming


【解决方案1】:

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

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();
                    }
                });

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

【讨论】:

  • 我认为您应该在这里使用 filter()mapNotNull()switchIfEmpty() 运算符
【解决方案2】:

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

我多年来使用 Webflux 学到的一些操作符:

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

我将分享我的 redisson 缓存和 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;
}

【讨论】:

    猜你喜欢
    • 2023-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    • 2021-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多