拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 使用WebClient获取JSON对象列表

使用WebClient获取JSON对象列表

白鹭 - 2021-11-24 603 0 0

1.概述

我们的服务通常与其他REST服务进行通信以获取信息。

从Spring 5开始,我们将使用WebClient以反应性,非阻塞的方式执行这些请求。 WebClient是新WebFlux框架的一部分,该框架基于Project Reactor构建。它具有流畅的反应式API,并且在其底层实现中使用HTTP协议。

当我们发出Web请求时,数据通常以JSON返回。 WebClient可以为我们转换此内容。

在这篇文章中,我们将介绍如何将一个JSON数组转换为Java ArrayObjectArray POJO的,和List使用POJO的WebClient

2.依赖关系

要使用WebClient,我们需要在pom.xml: 添加几个依赖项pom.xml:

<dependency>

 <groupId>org.springframework.boot</groupId>

 <artifactId>spring-boot-starter-webflux</artifactId>

 </dependency>

 <dependency>

 <groupId>org.projectreactor</groupId>

 <artifactId>reactor-spring</artifactId>

 <version>1.0.1.RELEASE</version>

 </dependency>

3. JSON,POJO和服务

让我们从端点http://localhost:8080/readers开始,该端点以JSON数组的形式返回读者及其喜爱的书籍的列表:

[{

 "id": 1,

 "name": "reader1",

 "favouriteBook": {

 "author": "Milan Kundera",

 "title": "The Unbearable Lightness of Being"

 }

我们将需要相应的ReaderBook类来处理数据:

public class Reader {

 private int id;

 private String name;

 private Book favouriteBook;



 // getters and setters..

 }
public class Book {

 private final String author;

 private final String title;



 // getters and setters..

 }

对于我们的接口实现,我们编写一个ReaderConsumerServiceImpl并将其作为WebClient的依赖项:

public class ReaderConsumerServiceImpl implements ReaderConsumerService {



 private final WebClient webClient;



 public ReaderConsumerServiceImpl(WebClient webclient) {

 this.webclient = webclient;

 }



 // ...

 }

4.映射JSON对象List

当我们从REST请求接收到JSON数组时,有多种方法可以将其转换为Java集合。让我们看一下各种选项,看看处理返回的数据有多么容易。我们将研究提取读者最喜欢的书。

4.1。 MonoFlux

Project Reactor引入了Publisher: **Mono**两种实现Publisher: **Mono****Flux**

当我们需要处理零到许多或可能无限的结果时, Flux<T>很有用。我们可以以Twitter供稿为例。

当我们知道一次返回所有结果时(如在用例中一样),我们可以使用Mono<T>

4.2。 WebClientObject数组

首先,让我们使用WebClient.get进行GET调用,并使用Object[]类型的Mono来收集响应:

Mono<Object[]> response = webClient.get()

 .accept(MediaType.APPLICATION_JSON)

 .retrieve()

 .bodyToMono(Object[].class).log();

接下来,让我们将主体提取到Object数组中:

Object[] objects = response.block();

实际的Object这里是包含我们的数据中的任意结构。让我们将其转换为Reader对象的数组。

为此,我们需要一个ObjectMapper

ObjectMapper mapper = new ObjectMapper();

在这里,我们将其声明为内联,尽管通常将其作为类的private static final成员来完成。

最后,我们准备提取读者喜爱的书籍并将其收集到列表中:

return Arrays.stream(objects)

 .map(object -> mapper.convertValue(object, Reader.class))

 .map(Reader::getFavouriteBook)

 .collect(Collectors.toList());

当我们要求Jackson的反序列化器将Object作为目标类型生成时,它实际上将JSON反序列化为一系列LinkedHashMap对象。使用convertValue后处理效率低下。如果我们在反序列化期间向Jackson提供所需的类型,则可以避免这种情况。

4.3。带Reader阵列的WebClient

我们可以向WebClient提供Reader[]而不是Object[]

Mono<Reader[]> response = webClient.get()

 .accept(MediaType.APPLICATION_JSON)

 .retrieve()

 .bodyToMono(Reader[].class).log();

 Reader[] readers = response.block();

 return Arrays.stream(readers)

 .map(Reader:getFavouriteBook)

 .collect(Collectors.toList());

在这里,我们可以看到我们不再需要ObjectMapper.convertValue 。但是,我们仍然需要进行其他转换以使用Java Stream API并使我们的代码与List一起使用。

4.4。带Reader List WebClient

如果我们希望Jackson生成ReaderList而不是数组,则需要描述我们要创建的List 。为此,我们向该方法提供一个由匿名内部类产生的ParameterizedTypeReference

Mono<List> response = webClient.get()

 .accept(MediaType.APPLICATION_JSON)

 .retrieve()

 .bodyToMono(new ParameterizedTypeReference<List>() {});

 List readers = response.block();



 return readers.stream()

 .map(Reader::getFavouriteBook)

 .collect(Collectors.toList());

这为我们提供了我们可以使用的List

让我们更深入地探讨为什么需要使用**ParameterizedTypeReference** .

当类型信息在运行时可用时,Spring的WebClient可以轻松地将JSON反序列化为Reader.class

但是,对于泛型,如果我们尝试使用List<Reader>.class ,则会发生类型擦除。因此,Jackson将无法确定泛型的类型参数。

通过使用ParameterizedTypeReference ,我们可以克服此问题。将其实例化为匿名内部类利用了以下事实:泛型类的子类包含编译时类型信息,该信息不受类型擦除的影响,可以通过反射使用。

5.结论

在本教程中,我们看到了使用WebClient处理JSON对象的三种不同方式.我们看到了指定Object数组类型和我们自己的自定义类的方法。

然后,我们学习了如何使用ParameterizedTypeReference提供类型信息以生成List

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *