Get and Post Lists of Objects with RestTemplate – 用RestTemplate获取和发布对象的列表

最后修改: 2018年 6月 21日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

The RestTemplate class is the central tool for performing client-side HTTP operations in Spring. It provides several utility methods for building HTTP requests and handling responses.

RestTemplate类是Spring中执行客户端HTTP操作的核心工具。它为构建HTTP请求和处理响应提供了几种实用方法。

And since RestTemplate integrates well with Jackson, it can serialize/deserialize most objects to and from JSON without much effort. However, working with collections of objects is not so straightforward.

由于RestTemplateJackson整合得很好,它可以不费吹灰之力将大多数对象序列化/反序列化成JSON。然而,处理对象的集合就不那么简单了

In this tutorial, we’ll learn how to use RestTemplate to GET and POST a list of objects.

在本教程中,我们将学习如何使用RestTemplateGETPOST一个对象列表。

2. Example Service

2.服务实例

We’ll be using an employee API that has two HTTP endpoints, get all and create:

我们将使用一个雇员API,它有两个HTTP端点,即获取所有和创建。

  • GET /employees
  • POST /employees

For communication between the client and server, we’ll use a simple DTO to encapsulate basic employee data:

对于客户端和服务器之间的通信,我们将使用一个简单的DTO来封装基本的雇员数据。

public class Employee {
    public long id;
    public String title;

    // standard constructor and setters/getters
}

Now we’re ready to write code that uses RestTemplate to get and create lists of Employee objects.

现在我们准备编写代码,使用RestTemplate来获取和创建Employee对象的列表。

3. Get a List of Objects With RestTemplate

3.用RestTemplate获取一个对象列表

Normally when calling GET, we can use one of the simplified methods in RestTemplate, such as:

通常在调用GET时,我们可以使用RestTemplate中的一个简化方法,例如:

getForObject(URI url, Class<T> responseType)

getForObject(URI url, Class<T> responseType)

This sends a request to the specified URI using the GET verb, and converts the response body into the requested Java type. This works great for most classes, but it has a limitation; we can’t send lists of objects.

它使用GET动词向指定的URI发送请求,并将响应体转换为请求的Java类型。这对大多数类都很有效,但它有一个限制;我们不能发送对象的列表。

The problem is due to type erasure with Java generics. When the application is running, it has no knowledge of what type of object is in the list. This means the data in the list can’t be deserialized into the appropriate type.

这个问题是由于Java泛型的类型擦除造成的。当应用程序运行时,它不知道列表中的对象是什么类型。这意味着列表中的数据无法被反序列化为适当的类型。

Luckily, we have two options to get around this.

幸运的是,我们有两个选择来解决这个问题。

3.1. Using Arrays

3.1.使用数组

First, we can use RestTemplate.getForEntity() to GET an array of objects via the responseType parameter. Whatever class we specify there will match ResponseEntity‘s parameter type:

首先,我们可以使用RestTemplate.getForEntity() 通过responseType参数来获取一个对象阵列。无论我们在这里指定什么,都将与ResponseEntity的参数类型匹配。

ResponseEntity<Employee[]> response =
  restTemplate.getForEntity(
  "http://localhost:8080/employees/",
  Employee[].class);
Employee[] employees = response.getBody();

We could also have used RestTemplate.exchange to achieve the same result.

我们也可以使用RestTemplate.exchange来实现同样的结果。

Note that the collaborator doing the heavy lifting here is ResponseExtractor, so if we need further customization, we can call execute and provide our own instance.

请注意,在这里做繁重工作的合作者是ResponseExtractor,所以如果我们需要进一步定制,我们可以调用execute并提供我们自己的实例。

3.2. Using a Wrapper Class

3.2.使用一个封装类

Some APIs will return a top-level object that contains the list of employees instead of returning the list directly. To handle this situation, we can use a wrapper class that contains the list of employees.

一些API会返回一个包含雇员列表的顶层对象,而不是直接返回列表。为了处理这种情况,我们可以使用一个包含雇员列表的封装类。

public class EmployeeList {
    private List<Employee> employees;

    public EmployeeList() {
        employees = new ArrayList<>();
    }

    // standard constructor and getter/setter
}

Now we can use the simpler getForObject() method to get the list of employees:

现在我们可以使用更简单的getForObject()方法来获得雇员的列表。

EmployeeList response = restTemplate.getForObject(
  "http://localhost:8080/employees",
  EmployeeList.class);
List<Employee> employees = response.getEmployees();

This code is much simpler, but requires an additional wrapper object.

这段代码要简单得多,但需要一个额外的封装对象。

4. Post a List of Objects With RestTemplate

4.用RestTemplate发布一个对象列表

Now let’s look at how to send a list of objects from our client to the server. Just like above, RestTemplate provides a simplified method for calling POST:

现在让我们来看看如何从我们的客户端向服务器发送一个对象的列表。就像上面一样,RestTemplate提供了一个简化的方法来调用POST。

postForObject(URI url, Object request, Class<T> responseType)

postForObject(URI url, Object request, Class<T> responseType)

This sends an HTTP POST to the given URI, with the optional request body, and converts the response into the specified type. Unlike the GET scenario above, we don’t have to worry about type erasure.

这将向给定的URI发送一个HTTP POST,带有可选的请求体,并将响应转换为指定的类型。与上面的GET方案不同,我们不必担心类型擦除的问题

This is because now we’re going from Java objects to JSON. The list of objects and their type are known by the JVM, so they’ll be properly serialized:

这是因为现在我们要从Java对象到JSON。对象的列表和它们的类型被JVM知道,所以它们会被正确地序列化。

List<Employee> newEmployees = new ArrayList<>();
newEmployees.add(new Employee(3, "Intern"));
newEmployees.add(new Employee(4, "CEO"));

restTemplate.postForObject(
  "http://localhost:8080/employees/",
  newEmployees,
  ResponseEntity.class);

4.1. Using a Wrapper Class

4.1.使用一个封装类

If we need to use a wrapper class to be consistent with the GET scenario above, that’s simple too. We can send a new list using RestTemplate:

如果我们需要使用一个封装类来与上面的GET方案一致,那也很简单。我们可以使用RestTemplate发送一个新列表。

List<Employee> newEmployees = new ArrayList<>();
newEmployees.add(new Employee(3, "Intern"));
newEmployees.add(new Employee(4, "CEO"));

restTemplate.postForObject(
  "http://localhost:8080/employees",
  new EmployeeList(newEmployees),
  ResponseEntity.class);

5. Conclusion

5.总结

Using RestTemplate is a simple way of building HTTP clients to communicate with our services.

使用RestTemplate是建立HTTP客户端与我们的服务进行通信的一种简单方法。

It provides a number of methods for working with every HTTP method and simple objects. With a little bit of extra code, we can easily use it to work with lists of objects.

它提供了许多方法来处理每个HTTP方法和简单的对象。通过一点额外的代码,我们可以很容易地使用它来处理对象的列表。

As usual, the complete code is available in the Github project.

像往常一样,完整的代码可以在Github项目中获得。