«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
);
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, поэтому его легко импортировать и запускать как есть.