Поговорим о RestTemplate

Java задняя часть .NET Spring

Недавно я использовал класс RestTemplate и потратил некоторое время, чтобы обобщить некоторые вещи, надеясь помочь всем.

Начиная с версии 3.0, Spring предоставляет RestTemplate в качестве клиента для доступа к службам Rest.RestTemplate предоставляет множество удобных методов для доступа к удаленным службам Http, которые могут значительно повысить эффективность написания клиентов.

Эта статья начнется с API, предоставляемого RestTemplate, сначала для понимания конкретного использования RestTemplate, а затем проанализирует несколько задействованных основных классов и, наконец, проанализирует весь процесс выполнения RestTemplate, длина относительно длинная, рекомендуется сначала Код быстрый!

Основной API

При обычном использовании мы обычно используем упакованные getForObject/getForEntity, postForObject/postForEntity/postForLocation, помещаем и удаляем.

получить обработку запроса

Возвращаемое значение метода getForEntity — это ResponseEntity, который представляет собой инкапсуляцию Spring ответа на HTTP-запрос, включая несколько важных элементов, таких как код ответа, contentType, contentLength и тело ответного сообщения.

  • url: адрес вызываемой службы
  • responseType: возвращаемый тип тела
  • uriVariables: есть две формы:
    • Вы можете использовать число в качестве заполнителя и, наконец, параметр переменной длины, чтобы заменить предыдущие заполнители один за другим.
    • Вы также можете использовать форму name={name}.Последний параметр — это карта, ключ карты — это имя предыдущего заполнителя, а значение карты — это значение параметра.

Тестовый пример типа ответа

Определенный ресурс контроллера:

Здесь тестируются разные типы ответов:

результат:

getForEntity(responseType=Map.class):{glmapper=hello glmapper}
getForEntity(responseType=String.class):{"glmapper":"hello glmapper"}

тестовый пример uriVariables

Давайте сначала рассмотрим метод без карты, два контроллера, два разных метода получения параметров (по сути одинаковые)

  • Способы использования заполнителей:

  • Как использовать карту:

getForObject

Функция getForObject на самом деле является дальнейшей инкапсуляцией функции getForEntity.Если вы обращаете внимание только на содержимое тела возвращаемого сообщения и не заботитесь о другой информации, вы можете использовать getForObject.

Вызов здесь немного проще, чем getForEntity, вы можете получить объект напрямую:

Несколько перегруженных методов getForObject в основном такие же, как и у getForEntity.

обработка пост-запроса

В RestTemplate запросы POST можно инициировать с помощью следующих трех методов: postForEntity, postForObject, postForLocation.

Случай postForEntity

Звоните, чтобы получить:

postForEntity(URI url, @Nullable Object request, Class<T> responseType)
  • Первый параметр метода представляет собой адрес вызываемой службы.
  • Второй параметр метода представляет загруженные параметры
  • Третий параметр метода указывает тип данных возвращаемого тела сообщения.

случай postForObject

В соответствии с getForObject, он обращает внимание только на возвращаемое тело сообщения.

Случай postForLocation

postForLocation также отправляет новый ресурс. После успешной отправки возвращается URI нового ресурса. Параметры postForLocation в основном такие же, как и два предыдущих параметра, но возвращаемое значение этого метода — Uri, для которого требуется только поставщик услуг, чтобы вернуть Uri.Этот Uri представляет расположение нового ресурса.

Здесь есть небольшая яма, нам нужно добавить этот uri в заголовок ответа, иначе мы получим null позже.

exchange

Отличие метода exchange от вышеописанных методов в том, что он требует еще один параметр типа запроса:

Асинхронный клиент AsyncRestTemplate

Асинхронная реализация RestTemplate. Используемый API в основном такой же, как RestTemplate. Разница в том, что RestTemplate возвращает результат напрямую, а AsyncRestTemplate возвращает ListenableFuture.

Перехватчик RestTemplate

Spring предоставляет два интерфейса, ClientHttpRequestInterceptor и AsyncClientHttpRequestInterceptor, которые могут перехватывать запросы, инициированные RestTemplate и AsyncRestTemplate соответственно, и изменять запрос или улучшать соответствующую информацию перед ее отправкой на сервер.

  • ClientHttpRequestInterceptor перехватывает RestTemplate

  • AsyncClientHttpRequestInterceptor перехватывает AsyncRestTemplate

Чтобы установить перехватчик, вы можете установить его через предоставленный setInterceptors:

Пользовательский ResponseErrorHandler

Интерфейс ResponseErrorHandler определяет, что делать, если в ответе возникает ошибка. Здесь мы настраиваем CustomResponseErrorHandler, когда возвращаемый код не равен 200, это означает, что выполнение пошло не так.

Установите ResponseErrorHandler:

Результаты:

Технологический поток

Разберем процесс обработки запроса в RestTemplate. На рисунке ниже XXXX представляет метод API, который мы вызываем. Общий процесс таков: выполните некоторую инкапсуляцию обработки запросов внутри API, затем передайте ее методу execute для выполнения, и, наконец, реальная обработка выполняется в методе doExecute.

Ниже приведен анализ процесса выполнения метода getForEntity:

Метод getForEntity:

  • На основе заданного типа ответа возвращает реализацию обратного вызова запроса, которая подготавливает запрос.
  • Средство извлечения ответов, которое возвращает ResponseEntity на основе заданного типа ответа.

метод выполнения:

  • В этом методе URL-адрес обрабатывается кодировкой urlencode и единообразно преобразуется в URL-адрес. Здесь мы также можем вручную закодировать параметры в сети.

doExecute — это метод собственно обработки запроса, сосредоточимся на процессе выполнения этого метода:

  • createRequest
  • doWithRequest
  • execute
  • handleResponse

1. создать запрос

Цель этого метода — создать объект ClientHttpRequest. RestTemplate интегрирует абстрактный класс HttpAccessor.Процесс создания ClientHttpRequest заключается в завершении создания конкретного запроса с помощью класса реализации ClientHttpRequestFactory по умолчанию SimpleClientHttpRequestFactory в его родительском классе HttpAccessor.

  • 1. Создайте объект java.net.HttpURLConnection.

  • 2. Установите соединение, включая connectTimeout, setDoInput и т. д.

  • 3. bufferRequestBody используется, чтобы указать, следует ли использовать форму кэшированного потока, значение по умолчанию — true. Недостаток в том, что при отправке большого количества данных, таких как put/post, происходит серьезное потребление памяти. Это значение может быть изменено SimpleClientHttpRequestFactory#setBufferRequestBody.

Изменения в разных версиях все еще относительно велики, когда вы читаете исходный код, вы все еще смотрите на последний код.

2. сделать с запросом

RequestCallback инкапсулирует тело запроса и объекты заголовка запроса. Здесь все HttpMessageConverters будут пройдены, проанализированы на все поддерживаемые MediaTypes и помещены в allSupportedMediaTypes.

request.getHeaders().setAccept(allSupportedMediaTypes);

RestTemplate соответствует реализации двух внутренних классов:

  • Обработка AcceptHeaderRequestCallback.doWithRequest. При отправке запроса в заголовке Http необходимо установить поле Accept, в котором указывается тип носителя (формат сообщения), принятый стороной, отправляющей запрос, а также тип носителя (формат сообщения) информации, которая должна быть возвращена ответчиком. . По третьему параметру responseType метода postForEntity программа выберет соответствующий парсер XXXConverter и найдет все поддерживаемые типы мультимедиа в соответствии с парсером.

  • Обработка HttpEntityRequestCallback.doWithRequest. Если это запрос POST и тело сообщения существует, в дополнение к установке поля Accept вам также может потребоваться установить поле Content-Type, которое указывает тип носителя (формат сообщения) отправленного запроса и тип носителя ( формат сообщения), принятый ответчиком. По второму параметру запроса метода postForEntity программа выберет соответствующий парсер XXXConverter и запишет сообщение запроса в выходной поток.

3. выполнить

Здесь заголовок/тело запроса будет инкапсулировано в соединение, после чего запрос будет отправлен. Отследите выполнение метода execute и найдите метод SimpleBufferingClientHttpRequest#executeInternal:

Вот пример SimpleBufferingClientHttpRequest для инкапсуляции тела запроса и заголовков запроса. Как видно из кода:

  • При удалении определяется нужно ли отправлять тело запроса установленным ранее параметром DoOutput и можно ли задать поток вывода.Если это запрос на удаление, то очевидно DoOutput=false, не будет процесса инкапсуляции тело запроса, то есть FileCopyUtils.copy(bufferedOutput не выполняется. , this.connection.getOutputStream()).

4. обработать ответ

Последняя часть — разбор ответа, с точки зрения кода — это в основном разбор ошибки. ErrorHandler здесь также упоминался ранее, а обработка исключений может быть настроена путем реализации ResponseErrorHandler.

резюме

В этой статье сначала рассказывается об использовании RestTemplate API, выбирается несколько и рассказывается о них.Для различных сценариев необходимо определить дополнительные детали использования. Затем кратко рассказывается о перехватчике, асинхронном RestTemplate и обработчике ошибок, а также приводятся примеры. Наконец, анализируется процесс выполнения RestTemplate. Часть процесса выполнения является лишь грубым наброском из-за недостатка места. Есть еще много деталей, которые нужно добавить со временем. Эта часть в основном зависит от того, как взаимодействует нижний уровень, передача параметры, которые были запрошены, и так далее.