我有一个Rest Conotroller,它返回一个Flux<String>
,但是当我尝试将其收集到一个列表中时,它是所有串联字符串中的一项。如何获得它作为实际列表?
控制器:
@RestController
public class TestRestController
{
@GetMapping( "/getflux" )
public Flux<String> getFlux()
{
return Flux.fromIterable(
Arrays.asList(
"String 1",
"String 2"
)
);
}
}
呼叫控制器:
//This returns as a list of one item: "String 1String 2
List<String> response = WebClient.builder()
.baseUrl( "http://localhost:" + port + "/" )
.build()
.get()
.uri( "/getflux" )
.retrieve()
.bodyToFlux( String.class )
.collectList()
.block();
如何获取实际列表?
答案 0 :(得分:1)
似乎是List<String>
反序列化的问题(例如List<Integer>
和许多其他类型都可以正常工作)。我试图调整Jackson的ObjectMapper配置,但失败了。也许您也应该自己尝试一下,甚至将问题提交给Jackson Github回购。
作为一种解决方法,您可以从控制器方法中返回Mono<List<String>>
:
@GetMapping("/getflux")
public Mono<List<String>> getFlux() {
return Flux.fromIterable(
Arrays.asList(
"String 1",
"String 2"
)
).collectList();
}
,然后这样称呼它:
List<String> block = WebClient.builder()
.baseUrl("http://localhost:" + 8080 + "/")
.build()
.get()
.uri("/getflux")
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<String>>() {
})
.block();
结果为["String 1","String 2"]
。直接从Web浏览器/ curl / etc中调用controller方法将返回相同的结果。
答案 1 :(得分:1)
经过研究,看来这是一个被标记为“按预期工作”的Spring错误。
https://github.com/spring-projects/spring-framework/issues/20807
这是预期的行为。默认情况下,字节数组,字节缓冲区和字符串被视为低级内容(序列化输出),并按原样呈现。实际上,Flux会流传输,并且每个字符串都会立即写入并刷新。
Jackson编码器显式退出了元素类型String。我意识到String和String的数组可以呈现为JSON,但是有两种处理String内容的方式,这是我们默认选择的方式。
唯一的解决方案是从不返回Flux<String>
,而是返回您创建的某些包装器类的列表。这样仍然可以使用Flux
和背压,并且Spring可以正确处理此类复杂的对象。
以下内容可完美运行:
@GetMapping("/getflux")
public Flux<List<StringWrapper>> getFlux() {
return Flux.fromIterable(
Arrays.asList(
new StringWrapper( "String 1" ),
new StringWrapper( "String 2" )
)
);
}