Рубрики
Без рубрики

Использование перехватчика пружинной пластины

Узнайте об использовании перехватчиков в приложении Spring с помощью RestTemplate.

Автор оригинала: baeldung.

1. Обзор

В этом уроке мы узнаем, как реализовать перехватчик Spring RestTemplate |/.

Мы рассмотрим пример, в котором мы создадим перехватчик, который добавляет пользовательский заголовок к ответу.

2. Сценарии использования перехватчика

Помимо модификации заголовка, некоторые другие случаи использования, в которых полезен перехватчик RestTemplate , являются:

  • Ведение журнала запросов и ответов
  • Повторная попытка запросов с настраиваемой стратегией отступления
  • Отклонение запроса на основе определенных параметров запроса
  • Изменение URL-адреса запроса

3. Создание перехватчика

В большинстве парадигм программирования перехватчики являются важной частью, которая позволяет программистам контролировать выполнение, перехватывая его. Spring framework также поддерживает множество перехватчиков для различных целей.

Spring RestTemplate позволяет добавлять перехватчики, реализующие интерфейс ClientHttpRequestInterceptor|/. Метод intercept(HttpRequest, byte[], ClientHttpRequestExecution) этого интерфейса перехватит данный запрос и вернет ответ, предоставив нам доступ к объектам request , body и execution .

Мы будем использовать аргумент ClientHttpRequestExecution для фактического выполнения и передачи запроса в последующую цепочку процессов.

В качестве первого шага давайте создадим класс перехватчика, который реализует ClientHttpRequestInterceptor интерфейс:

public class RestTemplateHeaderModifierInterceptor
  implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(
      HttpRequest request, 
      byte[] body, 
      ClientHttpRequestExecution execution) throws IOException {
 
        ClientHttpResponse response = execution.execute(request, body);
        response.getHeaders().add("Foo", "bar");
        return response;
    }
}

Наш перехватчик будет вызываться для каждого входящего запроса , и он добавит пользовательский заголовок Foo к каждому ответу, как только выполнение завершится и вернется.

Поскольку метод intercept() включал запрос и тело в качестве аргументов, также возможно внести любые изменения в запрос или даже отказать в выполнении запроса на основе определенных условий.

4. Настройка RestTemplate

Теперь, когда мы создали наш перехватчик, давайте создадим RestTemplate bean и добавим в него наш перехватчик:

@Configuration
public class RestClientConfig {

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();

        List interceptors
          = restTemplate.getInterceptors();
        if (CollectionUtils.isEmpty(interceptors)) {
            interceptors = new ArrayList<>();
        }
        interceptors.add(new RestTemplateHeaderModifierInterceptor());
        restTemplate.setInterceptors(interceptors);
        return restTemplate;
    }
}

В некоторых случаях к объекту RestTemplate уже могут быть добавлены перехватчики. Поэтому, чтобы убедиться, что все работает так, как ожидалось, наш код инициализирует список перехватчиков только в том случае, если он пуст.

Как показывает наш код, мы используем конструктор по умолчанию для создания объекта RestTemplate , но есть некоторые сценарии, в которых нам нужно дважды прочитать поток запроса/ответа.

Например, если мы хотим, чтобы наш перехватчик функционировал как регистратор запросов/ответов, нам нужно прочитать его дважды – первый раз перехватчиком и второй раз клиентом.

Реализация по умолчанию позволяет нам считывать поток ответов только один раз. Для удовлетворения таких конкретных сценариев Spring предоставляет специальный класс под названием Buffering ClientHttpRequestFactory. Как следует из названия, этот класс будет буферизировать запрос/ответ в памяти JVM для многократного использования.

Вот как объект RestTemplate инициализируется с помощью Буферизации ClientHttpRequestFactory для включения кэширования потока запросов/ответов:

RestTemplate restTemplate 
  = new RestTemplate(
    new BufferingClientHttpRequestFactory(
      new SimpleClientHttpRequestFactory()
    )
  );

5. Проверка Нашего Примера

Вот тестовый случай JUnit для тестирования нашего RestTemplate перехватчика:

public class RestTemplateItegrationTest {
    
    @Autowired
    RestTemplate restTemplate;

    @Test
    public void givenRestTemplate_whenRequested_thenLogAndModifyResponse() {
        LoginForm loginForm = new LoginForm("username", "password");
        HttpEntity requestEntity
          = new HttpEntity(loginForm);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        
        ResponseEntity responseEntity
          = restTemplate.postForEntity(
            "http://httpbin.org/post", requestEntity, String.class
          );
        
        assertThat(
          responseEntity.getStatusCode(),
          is(equalTo(HttpStatus.OK))
        );
        assertThat(
          responseEntity.getHeaders().get("Foo").get(0),
          is(equalTo("bar"))
        );
    }
}

Здесь мы использовали свободно размещенную службу HTTP-запросов и ответов http://httpbin.org для публикации ваших данных. Эта служба тестирования вернет тело нашего запроса вместе с некоторыми метаданными.

6. Заключение

В этом руководстве рассказывается о том, как настроить перехватчик и добавить его в объект RestTemplate . Этот вид перехватчиков также может использоваться для фильтрации, мониторинга и управления входящими запросами.

Распространенным вариантом использования перехватчика RestTemplate является модификация заголовка, которую мы подробно проиллюстрировали в этой статье.

И, как всегда, вы можете найти пример кода в проекте Github . Это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.