Spring Boot RestTemplate
最后修改于 2023 年 7 月 28 日
Spring Boot RestTemplate教程展示了如何在Spring应用中使用RestTemplate
创建同步HTTP请求。
Spring 是一个流行的 Java 应用程序框架,而 Spring Boot 是 Spring 的一个演进,它有助于轻松创建独立的、生产级的基于 Spring 的应用程序。
RestTemplate
RestTemplate
是一个用于执行HTTP请求的同步客户端。它使用一个简单的模板方法API,基于底层的HTTP客户端库,如JDK HttpURLConnection、Apache HttpComponents等。
自Spring 5.0起,一个新的客户端WebClient
可用,可用于创建同步和异步请求。在未来的版本中,RestTemplate
将被弃用,转而使用WebClient
。
Spring Boot RestTemplate示例
在下面的应用程序中,我们创建一个自定义测试服务器,该服务器生成JSON数据,并使用RestTemplate
生成一个HTTP请求并使用返回的JSON数据。
创建JSON服务器
我们使用Node来创建用于我们目的的JSON测试服务器。
$ node --version v20.4.0
我们展示Node的版本。
$ npm init -y $ npm i -g json-server $ npm i @faker-js/faker fs
我们初始化一个Node项目并安装json-server
、faker
和fs
模块。json-server
用于创建测试JSON服务器,faker
用于生成测试数据,而fs
用于在JavaScript中处理文件系统。
import { faker } from '@faker-js/faker'; import { writeFileSync } from 'fs' function generateUsers() { let users = [] for (let id=1; id <= 100; id++) { let firstName = faker.person.firstName() let lastName = faker.person.lastName() let email = faker.internet.email() users.push({ "id": id, "first_name": firstName, "last_name": lastName, "email": email }) } return { "users": users } } let dataObj = generateUsers(); writeFileSync('data.json', JSON.stringify(dataObj, null, '\t'));
使用faker,我们生成一百个用户,其中包含id、名字、姓氏和电子邮件属性。数据被写入data.json
文件。该文件被json-server使用。
$ node generate_fake_users.js
我们生成一百个虚假用户。
$ json-server --watch data.json \{^_^}/ hi! Loading data.json Done Resources https://:3000/users Home https://:3000
我们启动json-server
。现在我们可以创建一个请求到https://:3000/users
资源,以获取一百个JSON格式的用户。
Spring Boot应用程序
我们创建一个Spring Boot应用程序。我们需要以下Maven依赖项和插件:spring-boot-starter
、spring-web
、jackson-databind
、spring-boot-starter-test
和spring-boot-maven-plugin
。
spring.main.banner-mode=off logging.level.root=INFO logging.pattern.console=%d{dd-MM-yyyy HH:mm:ss} %magenta([%thread]) %highlight(%-5level) %logger.%M - %msg%n myrest.url=https://:3000/users
application.properties
是Spring Boot中的主要配置文件。我们关闭Spring横幅,将日志级别设置为info,并设置控制台日志记录模式。我们还设置一个URL属性,该属性指向用户资源。该属性稍后将使用@Value
检索。
package com.zetcode.model; import com.fasterxml.jackson.annotation.JsonProperty; public class User { private int id; private String firstName; private String lastName; private String email; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstName() { return firstName; } @JsonProperty("first_name") public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } @JsonProperty("last_name") public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { final var sb = new StringBuilder("User{"); sb.append("id=").append(id); sb.append(", firstName='").append(firstName).append('\''); sb.append(", lastName='").append(lastName).append('\''); sb.append(", email='").append(email).append('\''); sb.append('}'); return sb.toString(); } }
User
bean映射到JSON用户对象。Spring使用Jackson库将JSON数据绑定到Java类。由于JSON属性与Java属性不匹配,我们使用@JsonProperty
来修复此问题。
package com.zetcode.config; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; import java.time.Duration; @Configuration public class AppConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder .setConnectTimeout(Duration.ofMillis(3000)) .setReadTimeout(Duration.ofMillis(3000)) .build(); } }
我们使用RestTemplateBuilder
创建一个配置bean。它设置了RestTemplate
。我们设置了连接和读取超时。
package com.zetcode.service; import com.zetcode.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class MyRestService { private final RestTemplate myRestTemplate; @Value("${myrest.url}") private String restUrl; @Autowired public MyRestService(RestTemplate myRestTemplate) { this.myRestTemplate = myRestTemplate; } public User[] getUsers() { return myRestTemplate.getForObject(restUrl, User[].class); } }
MyRestService
是生成HTTP请求的服务类。它从JSON测试服务器获取所有用户。
@Autowired public MyRestService(RestTemplate myRestTemplate) { this.myRestTemplate = myRestTemplate; }
我们注入RestTemplate
bean。
@Value("${myrest.url}") private String restUrl;
从配置中,我们使用@Value
注解获取URL。
var users = myRestTemplate.getForObject(restUrl, User[].class);
我们使用getForObject
方法生成请求。由于我们期望一个对象数组,我们使用User[].class
语法。
package com.zetcode; import com.zetcode.service.MyRestService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import java.util.Arrays; @Component public class MyRunner implements CommandLineRunner { private static final Logger logger = LoggerFactory.getLogger(MyRunner.class); private final MyRestService myRestService; @Autowired public MyRunner(MyRestService myRestService) { this.myRestService = myRestService; } @Override public void run(String... args) throws Exception { var users = myRestService.getUsers(); Arrays.stream(users).limit(10).forEach(todo -> logger.info("{}", todo)); } }
MyRunner
使用MyRestService
获取用户。我们将前十个用户显示到控制台。
package com.zetcode; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Application
是设置 Spring Boot 应用程序的入口点。
package com.zetcode; import com.zetcode.config.AppConfig; import com.zetcode.service.MyRestService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.client.RestClientTest; import java.util.Arrays; import static org.assertj.core.api.Assertions.assertThat; @RestClientTest(value = {MyRestService.class, AppConfig.class}) public class ApplicationTests { @Autowired private MyRestService service; @Test public void usersNotEmpty() throws Exception { var users = this.service.getUsers(); assertThat(users).isNotEmpty(); } @Test public void hasSizeOneHundred() throws Exception { var users = this.service.getUsers(); assertThat(users).hasSize(100); System.out.println(Arrays.toString(users)); } }
我们测试getUsers
服务方法。我们测试JSON数据不为空,并且它包含一百个元素。
@RestClientTest(value={MyRestService.class, AppConfig.class})
@RestClientTest
注解用于测试Spring rest客户端。它禁用完全自动配置,并且仅应用与rest客户端测试相关的配置。
$ ./gradlew bootRun ... ... - User{id=1, firstName='Ofelia', lastName='Hintz', email='Gustave.Von43@yahoo.com'} ... - User{id=2, firstName='Brian', lastName='Marvin', email='Marina.Shields@hotmail.com'} ... - User{id=3, firstName='Adah', lastName='Marquardt', email='Osbaldo_Halvorson55@hotmail.com'} ... - User{id=4, firstName='Jaycee', lastName='Kulas', email='Claud85@gmail.com'} ...
我们运行应用程序。
在本文中,我们展示了如何使用RestTemplate
在Spring应用程序中创建同步请求。REST数据来自Node创建的测试JSON服务器。