Выполнение HTTP-запроса с помощью Spring WebClient: GET

RedDeveloper
25.04.2023 08:32
Выполнение HTTP-запроса с помощью Spring WebClient: GET

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

Почему в Python есть оператор &quot;pass&quot;?
Почему в Python есть оператор "pass"?

05.05.2023 14:00

Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.

Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом

05.05.2023 11:59

Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря своим методам, они делают код очень простым для понимания и читабельным.

JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы

05.05.2023 11:57

Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний, то, не теряя времени, практикуйте наш бесплатный онлайн тест 1100+ JavaScript MCQs и развивайте свои навыки и знания.

Массив зависимостей в React
Массив зависимостей в React

05.05.2023 09:44

Все о массиве Dependency и его связи с useEffect.

Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий

05.05.2023 09:26

Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут вам настроить, как будет выглядеть ваш сайт Temple, и вы можете настроить его дизайн в зависимости от ваших потребностей в дополнение к более чем 15+...