spring webflux webclient响应将字符串列表转换为字符串

Abh*_*av 4 mono spring java-8 spring-boot spring-webflux

回复:

[ 
 {
  "version": "1.0",
  "content": [
    "12345",
    "67076",
    "123462",
    "604340",
    "1331999",
    "1332608",
    "1785581",
   ]
 }
]
Run Code Online (Sandbox Code Playgroud)

代码:

Mono<List<String>> mp = webClient.get().uri(accountMgmtURI)
    .retrieve()
    .bodyToMono(Map.class)
    .flatMap(trans-> {
       List<String> content= (List<String>) trans.get("content");
       System.out.println("content :: "+content);
       return Mono.just(content);
     }); 
System.out.println("content :: "+mp.toString()); 
String sites=mp.toString();
Run Code Online (Sandbox Code Playgroud)

g00*_*00b 9

第一个问题是您使用的 API 不是返回单个对象,而是返回一个对象数组,由方括号 ( [])指示。

这意味着你至少应该重构你的代码来bodyToFlux()代替bodyToMono()

client
    .get()
    .retrieve()
    // bodyToFlux() in stead of bodyToMono(
    .bodyToFlux(Map.class)
    // ...
Run Code Online (Sandbox Code Playgroud)

第二个问题是Map在这种情况下使用 a 并不容易,因为您必须一直强制转换所有内容,因为您无法传递任何泛型。与合适的班级一起工作,会使事情变得更容易。例如,您可以编写以下类:

public class VersionContent {
    private String version;
    private List<String> content;

    // TODO: Getters + Setters
}
Run Code Online (Sandbox Code Playgroud)

并将您的代码更改为:

client
    .get()
    .retrieve()
    .bodyToFlux(VersionContent.class)
    .map(VersionContent::getContent)
    .flatMap(Flux::fromIterable)
    // ...
Run Code Online (Sandbox Code Playgroud)

这段代码将检索每个对象的内容,并flatMap单独发出每个单独的值。


现在,content数组中的每个项目都将单独发布。这将我们带到了第三个问题,即您没有连接字符串。

要连接项目,您可以使用reduce()运算符:

client
    .get()
    .retrieve()
    .bodyToFlux(VersionContent.class)
    .map(VersionContent::getContent)
    .flatMap(Flux::fromIterable)
    // reduce() can be used to merge all individual items to a single item
    .reduce((sites, site) -> sites + "|" + site)
    // ...
Run Code Online (Sandbox Code Playgroud)

最后一个问题是您正在使用toString(),这是行不通的。反应式编程的关键方面之一是一切都是异步发生的。这意味着如果你试图在主线程中对你的数据做任何事情,什么都不会发生。

此外,出版商的另一个特点喜欢Mono并且Flux是他们懒惰。如果没有适当的订阅,什么都不会发生。

解决方案是正确subscribe()获取您的价值,例如:

client
    .get()
    .retrieve()
    .bodyToFlux(VersionContent.class)
    .map(VersionContent::getContent)
    .flatMap(Flux::fromIterable)
    .reduce((sites, site) -> sites + "|" + site)
    .subscribe(System.out::println);
Run Code Online (Sandbox Code Playgroud)

对于您的示例,上面的代码会将以下内容打印到控制台:

12345|67076|123462|604390|1331999|1332608|1785581
Run Code Online (Sandbox Code Playgroud)

请注意,这也意味着您要对这些站点执行的每个操作都应异步完成。

如果你不想异步工作,你可以block()像这样使用操作符:

12345|67076|123462|604390|1331999|1332608|1785581
Run Code Online (Sandbox Code Playgroud)