如何以非阻塞方式解析 Spring 5 WebClient 响应?
How to parse a Spring 5 WebClient response in a non-blocking way?
我正在使用 Spring WebFlux WebClient 从外部 API 检索数据,如下所示:
public WeatherWebClient() {
this.weatherWebClient = WebClient.create("http://api.openweathermap.org/data/2.5/weather");
}
public Mono<String> getWeatherByCityName(String cityName) {
return weatherWebClient
.get()
.uri(uriBuilder -> uriBuilder
.queryParam("q", cityName)
.queryParam("units", "metric")
.queryParam("appid", API_KEY)
.build())
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class);
}
这工作正常并产生如下响应:
{
"coord":{
"lon":-47.06,
"lat":-22.91
},
"weather":[
{
"id":800,
"main":"Clear",
"description":"clear sky",
"icon":"01d"
}
],
"base":"stations",
"main":{
"temp":16,
"pressure":1020,
"humidity":67,
"temp_min":16,
"temp_max":16
},
"visibility":10000,
"wind":{
"speed":1,
"deg":90
},
"clouds":{
"all":0
},
"dt":1527937200,
"sys":{
"type":1,
"id":4521,
"message":0.0038,
"country":"BR",
"sunrise":1527932532,
"sunset":1527971422
},
"id":3467865,
"name":"Campinas",
"cod":200
}
但我只对 "temp" 属性 (main -> temp) 感兴趣。我如何才能以 reactive/non-blocking 的方式将响应(例如使用 Jackson 的 ObjectMapper)转换为仅 return "temp" 值?
我知道首先要用“.exchange()”替换“.retrieve()”,但我不知道如何让它工作。
PS:这是我的第一个问题。如果我做错了什么或者您需要更多详细信息,请告诉我。
谢谢!
您需要创建一个与服务器发送的响应相对应的类型。一个非常小的例子可能是这样的:
@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherResponse {
public MainWeatherData main;
}
而 MainWeatherData
class 可能是:
@JsonIgnoreProperties(ignoreUnknown = true)
public class MainWeatherData {
public String temp;
}
最后,您可以在 bodyToMono
中使用 WeatherResponse
:
...
.retrieve()
.bodyToMono(WeatherResponse.class);
@JsonIgnoreProperties(ignoreUnknown = true)
注解指示 Jackson 在遇到 JSON 字符串中不存在于您的 POJO 中的任何值时不要给出任何错误。
您可以使用链式 map
运算符访问 WeatherResponse
对象:
getWeatherByCityName(cityName)
.map(weatherResponse -> weatherResponse.main.temp)
我正在使用 Spring WebFlux WebClient 从外部 API 检索数据,如下所示:
public WeatherWebClient() {
this.weatherWebClient = WebClient.create("http://api.openweathermap.org/data/2.5/weather");
}
public Mono<String> getWeatherByCityName(String cityName) {
return weatherWebClient
.get()
.uri(uriBuilder -> uriBuilder
.queryParam("q", cityName)
.queryParam("units", "metric")
.queryParam("appid", API_KEY)
.build())
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class);
}
这工作正常并产生如下响应:
{
"coord":{
"lon":-47.06,
"lat":-22.91
},
"weather":[
{
"id":800,
"main":"Clear",
"description":"clear sky",
"icon":"01d"
}
],
"base":"stations",
"main":{
"temp":16,
"pressure":1020,
"humidity":67,
"temp_min":16,
"temp_max":16
},
"visibility":10000,
"wind":{
"speed":1,
"deg":90
},
"clouds":{
"all":0
},
"dt":1527937200,
"sys":{
"type":1,
"id":4521,
"message":0.0038,
"country":"BR",
"sunrise":1527932532,
"sunset":1527971422
},
"id":3467865,
"name":"Campinas",
"cod":200
}
但我只对 "temp" 属性 (main -> temp) 感兴趣。我如何才能以 reactive/non-blocking 的方式将响应(例如使用 Jackson 的 ObjectMapper)转换为仅 return "temp" 值?
我知道首先要用“.exchange()”替换“.retrieve()”,但我不知道如何让它工作。
PS:这是我的第一个问题。如果我做错了什么或者您需要更多详细信息,请告诉我。
谢谢!
您需要创建一个与服务器发送的响应相对应的类型。一个非常小的例子可能是这样的:
@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherResponse {
public MainWeatherData main;
}
而 MainWeatherData
class 可能是:
@JsonIgnoreProperties(ignoreUnknown = true)
public class MainWeatherData {
public String temp;
}
最后,您可以在 bodyToMono
中使用 WeatherResponse
:
...
.retrieve()
.bodyToMono(WeatherResponse.class);
@JsonIgnoreProperties(ignoreUnknown = true)
注解指示 Jackson 在遇到 JSON 字符串中不存在于您的 POJO 中的任何值时不要给出任何错误。
您可以使用链式 map
运算符访问 WeatherResponse
对象:
getWeatherByCityName(cityName)
.map(weatherResponse -> weatherResponse.main.temp)