
WebClient - это реактивный веб-клиент, представленный в Spring 5. Это реактивное, неблокирующее решение, работающее по протоколу HTTP/1.1.
WebClient разрабатывается как альтернатива RestTemplate и поддерживает синхронизацию/асинхронизацию и неблокирующие операции. Поскольку RestTemplate находится в режиме обслуживания, нам следует ознакомиться с WebClient.
Чтобы использовать WebClient, нам необходимо добавить зависимость WebFlux.
Сборка с помощью Maven: pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
Сборка с помощью Gradle: build.gradle
dependencies {
compile 'org.springframework.boot:spring-boot-starter-webflux'
}Существует три способа создания экземпляра WebClient.
Первый способ создания экземпляра WebClient - это создание с настройками по умолчанию.
WebClient client = WebClient.create();
Второй способ - это создание путем передачи базового URI в качестве параметра. Этот вариант также создает экземпляр WebClient с настройками по умолчанию.
WebClient client = WebClient.create("http://localhost:8080");Последний способ - создание полностью настраиваемого экземпляра с помощью DefaultWebClientBuilder. Это самый продвинутый способ создания экземпляра WebClient.
WebClient client = WebClient.builder()
.baseUrl("http://localhost:8080")
.defaultCookie("cookieKey", "cookieValue")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080"))
.build();Давайте создадим простой проект для лучшего понимания. В этом проекте мы будем получать данные пользователя из публичного api random-data-api .
Чтобы сделать этот проект, нам нужно добавить только две зависимости: Spring Web и WebFlux.
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> </dependencies>
URI api - это https://random-data-api.com/api/v2/users . Я запишу его в application.properties как API_URI.
Application.properties
API_URI= https://random-data-api.com/api/v2/users
Теперь нам нужно создать боб WebClient, чтобы он использовался Spring.
@Configuration
public class WebClientConfig {
@Bean
public WebClient getWebClient(@Value("${API_URI}") String apiURI){
return WebClient.builder().baseUrl(apiURI).build();
}
}Мы не будем использовать все ключи ответа, поэтому нам нужно создать пользовательскую модель User.
public record User(String username,
String gender,
String first_name,
String last_name,
String email) {
}При создании модели обратите внимание на то, чтобы переменные назывались так же, как и в случае с ответом. За исключением случаев, когда необходимо использовать аннотацию JsonProperty.
@JsonIgnoreProperties(ignoreUnknown = true)
public record User(@JsonProperty("username") String un,
@JsonProperty("gender") String g,
@JsonProperty("first_name") String fn,
@JsonProperty("last_name") String ln,
@JsonProperty("email") String e) {
}Чтобы использовать WebClient, нам нужно создать сервис, который будет получать данные из API_URI.
@Service
public class UserService {
private final WebClient webClient;
public UserService(WebClient webClient) {
this.webClient = webClient;
}
public Mono<User> GetRandomUserFromWebClient(){
return webClient.get()
.retrieve()
.bodyToMono(User.class)
.retryWhen(Retry.fixedDelay(2, Duration.ofSeconds(1)))
.doOnError(error -> logger.error("There is an error while sending request {}", error.getMessage()))
.onErrorResume(error -> Mono.just(
new User(null,
null,
null,
null,
null)));
}
}Если вы хотите использовать WebClient синхронно, как RestTemplate, вы можете использовать метод .block().
Наконец, мы создадим контроллер для обработки HTTP-запросов.
@RestController
@RequestMapping("api/v1/user")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public Mono<User> getRandomUser(){
return userService.GetRandomUserFromWebClient();
}
}Теперь мы готовы к тестированию нашего проекта.

Мы также можем писать тесты для WebClient, используя WebTestClient. WebTestClient имеет множество мощных методов для тестирования.
class UserServiceTest {
WebTestClient webTestClient;
@BeforeEach
void setUp(){
webTestClient = WebTestClient.bindToServer().baseUrl("https://random-data-api.com/api/v2/users").build();
}
@Test
void getRandomUserFromWebClient() {
webTestClient.get()
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectBody();
}
}В заключение, поскольку RestTemplate находится в режиме обслуживания, WebClient является мощной альтернативой для него. Спасибо, что дочитали до конца. Надеюсь, вам понравилось содержание. Я приветствую вашу критику. Вы можете получить репо на Github с здесь .
Источники, которые очень помогли мне в процессе обучения:
https://www.baeldung.com/spring-5-webclient
Spring WebClient: Yeni Nesil Reactive HTTP Client

20.08.2023 18:21
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2026-2027 годах? Или это полная лажа?".

20.08.2023 17:46
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.

19.08.2023 18:39
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.
19.08.2023 17:22
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!

18.08.2023 20:33
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.

14.08.2023 14:49
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.