java - 带有新标头的 Spring WebClient 重试逻辑
问题描述
我正在尝试使用 Spring 构建重试逻辑WebClient
。我要解决的问题非常简单。我正在调用 API 端点来获取一些值。如果 API 返回带有 401 响应的错误,那么我将不得不调用令牌服务并更新我的令牌并使用新令牌并进行相同的 API 调用。
一般的psudo是
try {
GET /locations data
} catch(401 Unauthorized) {
POST /token and get renew Token --> This is another WebClient API call With New Token
call again GET /locations and return value
} catch (Another Exception) {
throw Application Error
}
这是我正在尝试执行的 Spring 代码,但它看起来并不工作。关于如何做的任何建议。
public List<Location> getLocations(final User user) {
if (null == user) {
throw new ApplicationException("User cannot be null");
}
if (null == user.getHoneyWellLinkToken()) {
throw new ApplicationException(String.format("%s has not linked the account with Honeywell", user.getUsername()));
}
List<Location> locations = getLocationsAPI(user).block();
return locations;
}
private Mono<List<Location>> getLocationsAPI(final User user) {
String endpoint = config.getApi().getLocationsEndpoint()
.concat("?apikey=")
.concat(config.getCredentials().getClientId());
return WebClient.builder().baseUrl(endpoint)
.build()
.get()
.headers(httpHeaders -> httpHeaders.setBearerAuth(user.getHoneyWellLinkToken().getAccessToken()))
.retrieve()
.bodyToFlux(Location.class)
.collectList()
.doOnError(err -> {
WebClient.builder().baseUrl(endpoint)
.build()
.get()
.headers(httpHeaders -> httpHeaders.setBearerAuth(honeywellService.renewToken(user).block().getHoneyWellLinkToken().getAccessToken()))
.retrieve().bodyToFlux(Location.class);
});
}
此代码托管在 GitHub 上https://github.com/reflexdemon/home-use/blob/main/src/main/java/io/vpv/homeuse/service/HoneywellThermostatService.java
解决方案
- 使用
onErrorResume
代替doOnError
block
更新令牌时不要
private Mono<List<Location>> getLocationsAPI(final User user) {
String endpoint = config.getApi().getLocationsEndpoint()
.concat("?apikey=")
.concat(config.getCredentials().getClientId());
return getLocations(endpoint, user)
.onErrorResume(err -> honeywellService.renewToken(user)
.flatMap(newUser -> getLocations(endpoint, newUser)));
}
private Mono<List<Location>> getLocations(String endpoint, User user) {
return WebClient.builder()
.baseUrl(endpoint)
.build()
.get()
.headers(httpHeaders -> httpHeaders.setBearerAuth(user
.getHoneyWellLinkToken()
.getAccessToken()))
.retrieve()
.bodyToFlux(Location.class)
.collectList();
}
此外,最好使用单个WebClient
实例而不是为每个请求构建一个新实例。
推荐阅读
- amazon-web-services - AWS Athena 表创建失败,“在输入‘创建外部’时没有可行的替代方案”
- image - 如何在 YOLO v3 输出显示视频中捕获框边界图像
- javascript - 网站代码在 Chrome 和 Firefox、桌面或移动设备上运行良好,但在 Safari 上无法运行
- asp.net-mvc - asp.net MVC Webgrid 操作列不起作用
- mariadb - 使用 azure cli 将 maria db 迁移到 azure sql
- api - 无法转换货币 paypal pay API 错误
- clojure - lein test 无法使用 clojure hystrix 正确返回退出代码
- html - 如何在Angular 6中选择特定字段
- apache-spark - Hive - 创建表 LIKE 在 spark-sql 中不起作用
- android - Jenkins Google Play Android Publisher 插件 androidApkMove 不在轨道之间移动发行说明