Используйте RestTemplate для вызовов сторонних сервисов Rest.

Spring Boot Java

1. Введение

RestTemplateдаSpringобеспечил звонокRestfulУровень абстракции для сервисов, упрощающий то же самое.RestfulСпособ связи сервиса скрывает некоторые ненужные детали, что позволяет более изящно заходить в приложениеRestfulСлужить . Но когдаSpring 5.0послеRestTemplateВ режиме обслуживания новые функции больше не разрабатываются, а выполняется только плановое обслуживание.SpringРекомендуется использовать поддержку как синхронного, так и асинхронногоStreamдругойAPI——WebClient. Но когдаSpring MVCНа данный момент у нас нет лучшего варианта.

2. Сценарии использования RestTemplate

Мы часто используем сторонниеRest APIУслуги, такие как текстовые сообщения, экспресс-запросы, прогноз погоды и т. д. Эти третьи лица предоставляют толькоRest Api, вы можете либо использоватьRestTemplateпозвонить им.

3. Инициализируйте RestTemplate

Пока ваш проект используетSpring MVCуже интегрированRestTemplate. Но обычно этот класс не внедряется автоматическиSpring IoCконтейнер, потому что многиеRest APIВсе они имеют особенности. Чтобы настроить более гибко, их класс конструкцииRestTemplateBuilderавтоматически вводитсяSpring IoCконтейнер. Мы можем инициализировать его так:

package cn.felord.rest.webclient;

import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
 * @author felord.cn
 * @since 14:58
 **/
@Component
public class SomeWeb {

    private final RestTemplateBuilder restTemplateBuilder;

    public SomeWeb(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplateBuilder = restTemplateBuilder;
    }

    public RestTemplate restTemplate() {
        // 通过 builder 定制
        return restTemplateBuilder.requestFactory(OkHttp3ClientHttpRequestFactory::new).
                build();
    }
}

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

2.1 Нижний слой RestTemplate

по умолчанию,RestTemplateиспользоватьjava.net.HttpURLConnectionВ качестве реализации, как только при его использовании возникает ненормальный статус ответа (например, 401), будет выдано исключение, поэтому мы обычно его не используем. мы можем переключиться наNetty,Apache HttpComponents,okHttpРеализация клиентской библиотеки по умолчанию, см.2серединаrequestFactory(ClientHttpRequestFactory factory)Метод доступа также может быть реализован сам по себеClientHttpRequestFactoryПодключайтесь к другим сторонним библиотекам для доступа. Здесь я используюokHttp. Вы можете настроить функции, предоставляемые этими сторонними библиотеками, чтобы обогатитьRestTemplate, например, установка времени ожидания запроса.

3. Примеры сценариев общих методов

RestTemplateподдерживать всехRestfulМетод стиля, вы можете выбрать в соответствии с вашими потребностями, здесь мы представляем только некоторые часто используемые методы. Поддерживаются все методыURIшаблоны иURIпараметр, который поддерживает следующие обозначения:

# 类似 spring mvc 中的 @PathVariable
https://api.apiopen.top/{method}

3.1 {get|post}ForEntity

GetПосле запроса сопоставьте ответ какResponseEntity<T>Объект ответа, объект-оболочка для тела ответа. Мы используем следующий код, чтобы случайным образом запросить 5 фотографий красивых девушек, которые вы можете распечатать для просмотра:

    @Autowired
    RestTemplate restTemplate;

    void contextLoads() {
        String url = "https://api.apiopen.top/getImages?page=0&count=5";
        ResponseEntity<String> responseEntity = restTemplate
                .getForEntity(url,String.class);
        String body = responseEntity.getBody();
        System.out.println("body = " + body);
    }

Приведенный выше метод изменяется на вариативные аргументы по порядку:

        String url = "https://api.apiopen.top/getImages?page={page}&count={count}";
        ResponseEntity<String> responseEntity = restTemplate
                .getForEntity(url,String.class,0,5);
        String body = responseEntity.getBody();
        System.out.println("body = " + body);

или использоватьMap<String,Object>:

        String url = "https://api.apiopen.top/getImages?page={page}&count={count}";
        HashMap<String, Object> uriParams = new HashMap<>();
        uriParams.put("page", 0);
        uriParams.put("count", 5);
        ResponseEntity<String> responseEntity = restTemplate
                .getForEntity(url, String.class, uriParams);
        String body = responseEntity.getBody();
        System.out.println("body = " + body);

postЗапрос дополнительно пройдет в возможномnullобъект VO илиMultiValueMapдля переноса параметров тела запроса, которые в конечном итоге будут инкапсулированы в

org.springframework.http.HttpEntityобъект, который может содержать следующие две части:

  • Объект тела запроса, вы можете использовать сущность VO,MultiValueMap
  • объект заголовка запроса,org.springframework.http.HttpHeaders
 String url = "https://api.apiopen.top/getImages?page={page}&count={count}";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<UserVO> httpEntity = new HttpEntity<>(new UserVO("userName"), headers);
        HashMap<String, Object> uriParams = new HashMap<>();
        uriParams.put("page", 0);
        uriParams.put("count", 5);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, httpEntity, String.class, uriParams);

Выше приведен пример вызова запроса Post с телом запроса и заголовками запроса.

3.2 {get|post}ForObject

Мы также можем сопоставить ответ непосредственно сPOJO, конечно, нужно хорошо понимать структуру результата ответа, рекомендуется отображать наStringПроверьте структуру. Мы приводим пример, другие примеры относятся к3.1 :

        String url = "https://api.apiopen.top/getImages?page={page}&count={count}";
        HashMap<String, Object> uriParams = new HashMap<>();
        uriParams.put("page", 0);
        uriParams.put("count", 5);
        String forObject = restTemplate.getForObject(url, String.class, uriParams);
        System.out.println("forObject = " + forObject);

3.3 headForHeaders

Этот метод используется для получения всехURIресурс объявления шаблонаHeader

        String url = "https://api.apiopen.top/getImages?page={page}&count={count}";
        HashMap<String, Object> uriParams = new HashMap<>();
        uriParams.put("page", 0);
        uriParams.put("count", 5);
        HttpHeaders httpHeaders = restTemplate.headForHeaders(url, uriParams);
        System.out.println(httpHeaders);

Результат:

[Access-Control-Allow-Headers:"Content-Type, x-requested-with, X-Custom-Header, Authorization", Access-Control-Allow-Methods:"POST, GET, OPTIONS, DELETE", Access-Control-Allow-Origin:"*", Access-Control-Max-Age:"3600", Cache-Control:"private", Content-Length:"608", Content-Type:"application/json;charset=UTF-8", Date:"Tue, 14 Apr 2020 15:25:19 GMT", Expires:"Thu, 01 Jan 1970 00:00:00 GMT"]

3.4 postForLocation

ДолженPostВместо того, чтобы возвращать полный ресурс, операция возвращает только что созданный URI ресурса. Например, загрузка файла возвращает запрошенный путь к ресурсу.

3.5 put/delete

Для запросов на размещение и удаление обратитесь к предыдущему API.

3.6 optionsForAllow

Этот метод получаетURIВсе разрешенные методы запроса, такие какПОЛУЧИТЬ, ПОСТАВИТЬ, ПОСТАВИТЬ, УДАЛИТЬодин или несколько из них.

3.7 exchange

Этот метод является общим методом запроса, который поддерживаетGET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE, когда вышеуказанный метод вас не удовлетворяет, вы можете использовать этот метод для настройки, этот метод предоставляет более гибкий API, например, вы можете настроитьGETЗаголовок запроса метода, помещенный вJwt Tokenи так далее, этоgetForObjectнесравненный.

4. Резюме

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

关注公众号:Felordcn获取更多资讯

Личный блог: https://felord.cn