原文: http://zetcode.com/springboot/resttemplate/

Spring Boot RestTemplate教程展示了如何在 Spring 应用中使用RestTemplate创建同步 HTTP 请求。

Spring 是流行的 Java 应用框架,而 Spring Boot 是 Spring 的演进,可以帮助轻松地创建独立的,生产级的基于 Spring 的应用。

RestTemplate

RestTemplate是执行 HTTP 请求的同步客户端。 它在基础 HTTP 客户端库(例如 JDK HttpURLConnection,Apache HttpComponents 等)上使用简单的模板方法 API。

从 Spring 5.0 开始,可以使用新客户端WebClient创建同步和异步请求。 在将来的版本中,将不推荐使用RestTemplate,而推荐使用WebClient

Spring Boot RestTemplate 示例

在以下应用中,我们创建一个自定义测试服务器,该服务器生成 JSON 数据,并使用RestTemplate生成 HTTP 请求并使用返回的 JSON 数据。

创建 JSON 服务器

为此,我们使用 Node 创建一个 JSON 测试服务器。

  1. $ node --version
  2. v11.2.0

我们显示 Node 的版本。

  1. $ npm init
  2. $ npm i -g json-server
  3. $ npm i faker fs

我们初始化 Node 项目并安装json-serverfakerfs模块。 json-server用于创建测试 JSON 服务器,faker用于生成测试数据,fs用于 JavaScript 中的文件系统。

generate_fake_users.js

  1. const faker = require('faker')
  2. const fs = require('fs')
  3. function generateUsers() {
  4. let users = []
  5. for (let id=1; id <= 100; id++) {
  6. let firstName = faker.name.firstName()
  7. let lastName = faker.name.lastName()
  8. let email = faker.internet.email()
  9. users.push({
  10. "id": id,
  11. "first_name": firstName,
  12. "last_name": lastName,
  13. "email": email
  14. })
  15. }
  16. return { "users": users }
  17. }
  18. let dataObj = generateUsers();
  19. fs.writeFileSync('data.json', JSON.stringify(dataObj, null, '\t'));

使用仿造者,我们可以生成具有 ID,名字,姓氏和电子邮件属性的一百个用户。 数据被写入data.json文件。 该文件由json-server使用。

  1. $ node generate_fake_users.js

我们产生了一百个假用户。

  1. $ json-server --watch data.json
  2. \{^_^}/ hi!
  3. Loading data.json
  4. Done
  5. Resources
  6. http://localhost:3000/users
  7. Home
  8. http://localhost:3000

我们开始json-server。 现在,我们可以向http://localhost:3000/users资源创建一个请求,以使用 JSON 获得一百个用户。

Spring Boot 应用

我们创建一个 Spring Boot 应用。 我们需要以下 Maven 依赖项和插件:spring-boot-starterspring-webjackson-databindspring-boot-starter-testspring-boot-maven-plugin

application.properties

  1. spring.main.banner-mode=off
  2. logging.level.root=INFO
  3. logging.pattern.console=%d{dd-MM-yyyy HH:mm:ss} %magenta([%thread]) %highlight(%-5level) %logger.%M - %msg%n
  4. myrest.url=http://localhost:3000/users

application.properties是 Spring Boot 中的主要配置文件。 我们关闭 Spring 横幅,将日志记录级别设置为 info,并设置控制台日志记录模式。 我们还设置了一个指向用户资源的 URL 属性。 稍后将使用@Value检索该属性。

User.java

  1. package com.zetcode.bean;
  2. import com.fasterxml.jackson.annotation.JsonProperty;
  3. public class User {
  4. private int id;
  5. private String firstName;
  6. private String lastName;
  7. private String email;
  8. public int getId() {
  9. return id;
  10. }
  11. public void setId(int id) {
  12. this.id = id;
  13. }
  14. public String getFirstName() {
  15. return firstName;
  16. }
  17. @JsonProperty("first_name")
  18. public void setFirstName(String firstName) {
  19. this.firstName = firstName;
  20. }
  21. public String getLastName() {
  22. return lastName;
  23. }
  24. @JsonProperty("last_name")
  25. public void setLastName(String lastName) {
  26. this.lastName = lastName;
  27. }
  28. public String getEmail() {
  29. return email;
  30. }
  31. public void setEmail(String email) {
  32. this.email = email;
  33. }
  34. @Override
  35. public String toString() {
  36. final var sb = new StringBuilder("User{");
  37. sb.append("id=").append(id);
  38. sb.append(", firstName='").append(firstName).append('\'');
  39. sb.append(", lastName='").append(lastName).append('\'');
  40. sb.append(", email='").append(email).append('\'');
  41. sb.append('}');
  42. return sb.toString();
  43. }
  44. }

User bean 映射到 JSON 用户对象。 Spring 使用 Jackson 库将 JSON 数据绑定到 Java 类。 由于 JSON 属性与 Java 属性不匹配,因此我们使用@JsonProperty来解决此问题。

AppConfig.java

  1. package com.zetcode.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.http.client.SimpleClientHttpRequestFactory;
  5. import org.springframework.web.client.RestTemplate;
  6. @Configuration
  7. public class AppConfig {
  8. @Bean
  9. public RestTemplate restTemplate() {
  10. var factory = new SimpleClientHttpRequestFactory();
  11. factory.setConnectTimeout(3000);
  12. factory.setReadTimeout(3000);
  13. return new RestTemplate(factory);
  14. }
  15. }

我们创建一个配置 bean。 设置RestTemplateSimpleClientHttpRequestFactory用于设置连接和读取超时。

AppConfig.java

  1. package com.zetcode.config;
  2. import org.springframework.boot.web.client.RestTemplateBuilder;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.client.RestTemplate;
  6. import java.time.Duration;
  7. @Configuration
  8. public class AppConfig {
  9. @Bean
  10. public RestTemplate restTemplate(RestTemplateBuilder builder) {
  11. return builder
  12. .setConnectTimeout(Duration.ofMillis(3000))
  13. .setReadTimeout(Duration.ofMillis(3000))
  14. .build();
  15. }
  16. }

或者,我们可以使用RestTemplateBuilder来完成这项工作。

MyRestService.java

  1. package com.zetcode.service;
  2. import com.zetcode.bean.User;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.beans.factory.annotation.Value;
  5. import org.springframework.stereotype.Service;
  6. import org.springframework.web.client.RestTemplate;
  7. @Service
  8. public class MyRestService {
  9. @Autowired
  10. private RestTemplate myRestTemplate;
  11. @Value("${myrest.url}")
  12. private String restUrl;
  13. public User[] getUsers() {
  14. var users = myRestTemplate.getForObject(restUrl, User[].class);
  15. return users;
  16. }
  17. }

MyRestService是生成 HTTP 请求的服务类。 它从 JSON 测试服务器获取所有用户。

  1. @Autowired
  2. private RestTemplate myRestTemplate;

我们注入了RestTemplate bean。

  1. @Value("${myrest.url}")
  2. private String restUrl;

从配置中,我们使用@Value注解获取 URL。

  1. var users = myRestTemplate.getForObject(restUrl, User[].class);

我们使用getForObject()方法生成请求。 由于我们期望对象数组,因此我们使用User[].class语法。

MyRunner.java

  1. package com.zetcode;
  2. import com.zetcode.service.MyRestService;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.CommandLineRunner;
  7. import org.springframework.stereotype.Component;
  8. import java.util.Arrays;
  9. @Component
  10. public class MyRunner implements CommandLineRunner {
  11. private static final Logger logger = LoggerFactory.getLogger(MyRunner.class);
  12. @Autowired
  13. private MyRestService myRestService;
  14. @Override
  15. public void run(String... args) throws Exception {
  16. var users = myRestService.getUsers();
  17. Arrays.stream(users).limit(10).forEach(todo -> logger.info("{}", todo));
  18. }
  19. }

MyRunner使用MyRestService获取用户。 我们向控制台显示前十个用户。

Application.java

  1. package com.zetcode;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class Application {
  6. public static void main(String[] args) {
  7. SpringApplication.run(Application.class, args);
  8. }
  9. }

Application是设置 Spring Boot 应用的入口。

ApplicationTests.java

  1. package com.zetcode;
  2. import com.zetcode.config.AppConfig;
  3. import com.zetcode.service.MyRestService;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. import static org.assertj.core.api.Assertions.assertThat;
  10. @RunWith(SpringRunner.class)
  11. @RestClientTest(value={MyRestService.class, AppConfig.class})
  12. public class ApplicationTests {
  13. @Autowired
  14. private MyRestService service;
  15. @Test
  16. public void usersNotEmpty() throws Exception {
  17. var users = this.service.getUsers();
  18. assertThat(users).isNotEmpty();
  19. }
  20. @Test
  21. public void hasSizeOneHundred() throws Exception {
  22. var users = this.service.getUsers();
  23. assertThat(users).hasSize(100);
  24. System.out.println(users);
  25. }
  26. }

我们测试getUsers()服务方法。 我们测试 JSON 数据不为空,并且包含一百个元素。

  1. @RestClientTest(value={MyRestService.class, AppConfig.class})

@RestClientTest注解用于测试 Spring rest 客户端。 它禁用完全自动配置,并且仅应用与其余客户端测试相关的配置。

  1. $ mvn -q spring-boot:run
  2. ...
  3. 27-11-2018 15:33:55 [main] INFO com.zetcode.MyRunner.lambda$run$0 - User{id=1, firstName='Ofelia', lastName='Hintz', email='Gustave.Von43@yahoo.com'}
  4. 27-11-2018 15:33:55 [main] INFO com.zetcode.MyRunner.lambda$run$0 - User{id=2, firstName='Brian', lastName='Marvin', email='Marina.Shields@hotmail.com'}
  5. 27-11-2018 15:33:55 [main] INFO com.zetcode.MyRunner.lambda$run$0 - User{id=3, firstName='Adah', lastName='Marquardt', email='Osbaldo_Halvorson55@hotmail.com'}
  6. 27-11-2018 15:33:55 [main] INFO com.zetcode.MyRunner.lambda$run$0 - User{id=4, firstName='Jaycee', lastName='Kulas', email='Claud85@gmail.com'}
  7. ...

我们运行该应用。

在本教程中,我们展示了如何在 Spring 应用中使用RestTemplate创建同步请求。 REST 数据来自 Node 创建的测试 JSON 服务器。 您可能也对相关教程感兴趣: Spring Boot @RestController教程Spring Boot H2 REST 教程Spring Boot RESTFul 应用Spring Boot REST Data JPA 教程Java 教程