Перейти к основному содержимому

Использование перехватчика Spring RestTemplate

· 3 мин. чтения

1. Обзор

В этом руководстве мы узнаем, как реализовать Spring RestTemplate `` Interceptor.

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

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

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

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

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

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

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

Мы будем использовать аргумент 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

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

@Configuration
public class RestClientConfig {

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

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

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

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

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

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

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

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<LoginForm> requestEntity
= new HttpEntity<LoginForm>(loginForm);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

ResponseEntity<String> responseEntity
= restTemplate.postForEntity(
"http://httpbin.org/post", requestEntity, String.class
);

Assertions.assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
Assertions.assertEquals(responseEntity.getHeaders()
.get("Foo")
.get(0), "bar");
}
}

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

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

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

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

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