我在反应式中使用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()
则发出默认Publisher
false
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;
}