Освоение Spring RestTemplate

Spring

предисловие

В области разработки Java-серверов Spring является неизбежной темой, особенно сейчас, когда преобладает концепция микросервисов, а появление Spring Boot вдохнуло новую жизнь в Spring, в дополнение к Spring Cloud, эти фреймворки позволяют использовать технологическую систему Spring. более обильный. Spring прошел итерацию с версии 1.0.0 в 2014 г. до версии 5.2.0 M1.Вслед за развитием языка Java постоянно появляются новые возможности и функции. Эта статья посвящена Spring Framework.RestTemplateсодержание, которое может сократить количество времени, которое мы обычно разрабатываем и используемHttpClientЗависимости API. Демонстрационный пример, включенный в статью, можно найти по адресу Github:Resttemplate demo. Спасибо Xiaoqi за серьезную корректуру.Если у вас есть какие-либо технические проблемы или упущения в статье, пожалуйста, оставьте сообщение и свяжитесь с нами, чтобы обсудить и обсудить вместе 😁.

знатьRestTemplate

Сначала мы учимся использоватьRestTemplateПеред этим давайте познакомимся с этим классом и посмотрим, как его официально описывает Spring. Из официальной документации APIRestTemplate javadocОписание этого класса можно найти следующим образом:

Synchronous client to perform HTTP requests, exposing a simple, template method API over underlying HTTP client libraries such as the JDK HttpURLConnection, Apache HttpComponents, and others. The RestTemplate offers templates for common scenarios by HTTP method, in addition to the generalized exchange and execute methods that support of less frequent cases.

Отсюда понятноRestTemplateКласс, который синхронно выполняет HTTP-запросы, а нижний уровень использует собственный JDK.HttpURLConnectionAPI илиHttpComponentsи другие библиотеки запросов HTTP-клиента. Еще один момент, который следует подчеркнуть, заключается в том, чтоRestTemplateПредоставляет шаблонный метод, облегчающий разработчикам отправку HTTP-запросов.

Примечательно,RestTemplateКлассы были представлены в Spring Framework 3.0, а версия Spring, которую мы здесь используем, — это последняя версия GA 5.1.6. В версии 5.0 и более поздних версиях более рекомендуется использовать неблокирующий адаптивный класс обработки HTTP-запросов.org.springframework.web.reactive.client.WebClientзаменитьRestTemplate, особенно в сценариях, соответствующих асинхронной обработке запросов.

Здесь мы кратко суммируем то, чтоRestTemplate:RestTemplateЭто класс, который Spring инкапсулирует для обработки синхронных HTTP-запросов. Подробнее о том, как использовать этот класс для операций HTTP-запросов, смотрите в собственно боевой части статьи.

Далее мы смотрим наRestTemplateКакие API предоставляет класс,RestTemplateПредоставляет около 30 методов запроса, большинство из которых представляют собой реализации перегрузки одного метода, здесь я в основном ссылаюсь на официальные документы.rest-client-accessКлассифицировать следующим образом:

имя метода описывать
getForObject Получить результат ответа через запрос GET
getForEntity Получено GET-запросомResponseEntityОбъект, содержащий код состояния, заголовки ответа и данные ответа
headForHeaders Возвращать все заголовки ответов как запросы HEAD для ресурсов
postForLocation Создать ресурс с POST-запросом и вернуть поля заголовка ответа в данных ответаLocationДанные
postForObject Создайте ресурс через запрос POST и получите результат ответа
put Создание или обновление ресурсов с помощью запросов PUT
patchForObject Обновите ресурсы, запросив PATH, и получите результат ответа. (ДжДКHttpURLConnectionНе поддерживает запросы режима PATH, поддерживаются другие клиентские библиотеки HTTP)
delete Удаление ресурса с помощью DELETE
optionsForAllow Все методы HTTP, которым разрешен доступ к ресурсу, могут быть получены путем запроса в режиме ALLOW, который можно использовать для просмотра того, какие методы запроса поддерживаются запросом.
exchange Более общая версия метода обработчика запросов, который принимаетRequestEntityObject, вы можете указать путь, заголовок запроса, запросить информацию и т. д. и, наконец, вернутьResponseEntityорганизация
execute Самый общий метод выполнения HTTP-запросов, все вышеперечисленные методы основаны наexecuteинкапсуляция, полный контроль информации запроса и получение данных ответа через интерфейс обратного вызова

Столько способов не помню, для лучшего понимания можно просто посмотреть.RestTemplateИерархию классов можно увидеть в официальном исходном коде:

/**
 * Interface specifying a basic set of RESTful operations.
 * Implemented by {@link RestTemplate}. Not often used directly, but a useful
 * option to enhance testability, as it can easily be mocked or stubbed.
 *
 * @author Arjen Poutsma
 * @author Juergen Hoeller
 * @since 3.0
 * @see RestTemplate
 */
public interface RestOperations {
					    ...
}

фактическиRestTemplateВсе методы запроса класса взяты изRestOperationsСудя по названию, вы, вероятно, знаете, что этот интерфейс в основном предоставляет интерфейс для операций запросов RESTful, таких как GET, POST, PUT, DELETE и т. д. Для получения подробной информации см.RestOperation javadoc.

RestTemplate 类层次图

О RESTFUL:

Определение из Википедии:Переходы состояний уровня представления, система, предназначенная для предоставления услуг World Wide Webстиль сборки ПО, также известный как REST для краткости.

Найдите ресурсы с URL-адресами и опишите операции с помощью HTTP-команд, таких как GET, POST, DELETE, PUT.Проще говоря, вы можете узнать, к каким ресурсам обращаться через URL-адрес, какую операцию выполнять с помощью HTTP-метода и результат выполнения с помощью кода состояния HTTP.

реальный бойRestTemplate

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

1. Создайте демонстрационный проект и импортируйте его в IDE.

Для того чтобы быстро собрать Демо мы используем фреймворк Spring Boot для сборки тут в первую очередь используем официально предоставленныйSpring InitializrЧтобы сгенерировать скелет проекта быстрой сборки, выберите Spring Boot версии 2.1.4, а базовой версией Spring Framework является последняя версия выпуска 5.1.6.Для зависимостей POM можно выбрать только один веб-модуль, что удобно для быстрого создания веб-приложений.

spring initializr

Нажмите кнопку «Создать проект», чтобы загрузить сжатый пакет проекта.После распаковки импортируйте проект с помощью собственной часто используемой среды IDE.Структура проекта организована следующим образом:

项目骨架

в проектеResttemplateApplication.javaBootstrap класс для всей программы, используемый для запуска проекта.

2. Напишите класс контроллера запроса ProductController.

Во-первых, чтобы иметь возможность использоватьRestTemplateОтправляйте HTTP-запросы несколькими способами, сначала создайте контроллер продукта, который принимает HTTP-запросы локально, а затем создайте новый пакет.com.one.learn.resttemplate.controller, создайте новый контроллер продуктаProductController, код показан ниже:

@RequestMapping("/product")
@RestController
public class ProductController {

    @GetMapping("/get_product1")
    public Product get_product1() {
        return new Product(1, "ProductA", BigDecimal.valueOf(6666.0));
    }

    @GetMapping("/get_product2")
    public Product get_product2(Integer id) {
        return new Product(id, "ProductC", BigDecimal.valueOf(6666.0));
    }

    @GetMapping("/get_product3")
    public String get_product3(Product product) {
        return product.toString();
    }


    @PostMapping("/post_product1")
    public String post_product1(Product product) {
        return product.toString();
    }

    @PostMapping("/post_product2")
    public String post_product2(@RequestBody Product product) {
        return product.toString();
    }

    @DeleteMapping("/delete/{id}")
    public String delete(@PathVariable Integer id) {
        String result = String.format("编号为%s的产品删除成功", id);
        System.out.println(result);
        return result;
    }

    @PutMapping("/update")
    public String updateByPut(Product product) {
        String result = product.toString() + " 更新成功";
        System.out.println(result);
        return result;
    }

    @PostMapping("/upload")
    public String upload(MultipartRequest request) {
 	       // Spring MVC 使用 MultipartRequest 接受带文件的 HTTP 请求
        MultipartFile file = request.getFile("file"); 
        String originalFilename = file.getOriginalFilename();
        return "upload success filename: " + originalFilename;
    }
}

существуетProductКлассы сущностей, задействованные в контроллереProductсоздан вcom.one.learn.resttemplate.beanПод пакетом код такой:

public class Product {
    private Integer id;
    private String name;
    private BigDecimal price;
    
    public Product() {
    }
    
    public Product(Integer id, String name, BigDecimal price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

			    // 省去 setter getter 方法
	
    @Override
    public String toString() {
        return "Product{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", price='" + price + '\'' +
                '}';
    }
}

С этими классами вы можете использовать классы начальной загрузки программыResttemplateApplicationЗапустите проект Spring Boot, и родится простое веб-приложение, прослушивающее порт 8080, и результат показан на следующем рисунке:

项目启动

Мы можем просто протестировать его, открыть браузер, посетитьhttp://localhost:8080/product/get_product1, вы увидите результат, как показано на рисунке:

项目访问

3. Напишите тестовый класс для отправки HTTP-запросов с помощью RestTemplate.

Теперь, когда у вас есть веб-служба, пришло время использоватьRestTemplateотправить запрос и обработать ответ. мы вtestСоздайте новый тестовый класс в файлеcom.one.learn.resttemplate.RestTemplateTests, код показан ниже:

public class RestTemplateTests {
    RestTemplate restTemplate = null;

    @Before
    public void setup() {
        restTemplate = new RestTemplate();
    }
    
}

Здесь мы пишем тестовый метод для использованияRestTemplateПара реализации APIProductЗапрос каждого интерфейса контроллера.

ПОЛУЧИТЬ запрос

Начнем с самого простого, попробуйте использоватьRestTemplateПуть запроса доступаproduct/get_product1, запрос GET без каких-либо параметров, код выглядит следующим образом:

@Test
public void testGet_product1() {
   String url = "http://localhost:8080/product/get_product1";
   //方式一:GET 方式获取 JSON 串数据
   String result = restTemplate.getForObject(url, String.class);
   System.out.println("get_product1返回结果:" + result);
   Assert.hasText(result, "get_product1返回结果为空");
	
	   //方式二:GET 方式获取 JSON 数据映射后的 Product 实体对象
   Product product = restTemplate.getForObject(url, Product.class);
   System.out.println("get_product1返回结果:" + product);
   Assert.notNull(product, "get_product1返回结果为空");
	
	   //方式三:GET 方式获取包含 Product 实体对象 的响应实体 ResponseEntity 对象,用 getBody() 获取
   ResponseEntity<Product> responseEntity = restTemplate.getForEntity(url, Product.class);
   System.out.println("get_product1返回结果:" + responseEntity);
   Assert.isTrue(responseEntity.getStatusCode().equals(HttpStatus.OK), "get_product1响应不成功");
   
}

Первый взгляд на метод текущего тестаtestGet_product1Выходной лог почтовой консоли:

...
get_product1返回结果:{"id":1,"name":"ProductA","price":6666.0}
...
get_product1返回结果:Product{id='1', name='ProductA', price='6666.0'}
...
get_product1返回结果:<200,Product{id='1', name='ProductA', price='6666.0'},[Content-Type:"application/json;charset=UTF-8", Transfer-Encoding:"chunked", Date:"Thu, 09 May 2019 15:37:25 GMT"]>
...

можно увидетьtestGet_product1На все запросы успешно ответили и данные получены.Из приведенного выше кода это очень просто? Теперь для немного более сложного метода запроса используйтеRestTemplateв APIexchangeиexecuteМетод отправляет запрос GET, который может более детально контролировать поведение запроса, напримерHeaderинформацию, методы обработки данных и т. д., а также вtestGet_product1Добавьте в метод следующий код:

@Test
public void testGet_product1() {
    String url = "http://localhost:8080/product/get_product1";
    //....
    
    //方式一: 构建请求实体 HttpEntity 对象,用于配置 Header 信息和请求参数
    MultiValueMap header = new LinkedMultiValueMap();
    header.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
    HttpEntity<Object> requestEntity = new HttpEntity<>(header);
    //方式二: 执行请求获取包含 Product 实体对象 的响应实体 ResponseEntity 对象,用 getBody() 获取
    ResponseEntity<Product> exchangeResult = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Product.class);
    System.out.println("get_product1返回结果:" + exchangeResult);
    Assert.isTrue(exchangeResult.getStatusCode().equals(HttpStatus.OK), "get_product1响应不成功");

    	//方式三: 根据 RequestCallback 接口实现类设置Header信息,用 ResponseExtractor 接口实现类读取响应数据
    String executeResult = restTemplate.execute(url, HttpMethod.GET, request -> {
        request.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
    }, (clientHttpResponse) -> {
        InputStream body = clientHttpResponse.getBody();
        byte[] bytes = new byte[body.available()];
        body.read(bytes);
        return new String(bytes);
    }); // 备注:这里使用了 Java8 特性:Lambda 表达式语法,若未接触 Lambda 表达式后可以使用匿名内部类代替实现
    System.out.println("get_product1返回结果:" + executeResult);
    Assert.hasText(executeResult, "get_product1返回结果为空");
}

Запустите тестовый метод еще разtestGet_product1Выходной лог почтовой консоли:

...
get_product1返回结果:<200,Product{id='1', name='ProductA', price='6666.0'},[Content-Type:"application/json;charset=UTF-8", Transfer-Encoding:"chunked", Date:"Thu, 09 May 2019 16:00:22 GMT"]>
...
get_product1返回结果:{"id":1,"name":"ProductA","price":6666.0}
...

Результаты также возвращаются нормально, указывая на то, что все выполненные запросы верны.

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

@Test
public void testGet_product2() {
    String url = "http://localhost:8080/product/get_product2/id={id}";
	
	    //方式一:将参数的值存在可变长度参数里,按照顺序进行参数匹配
    ResponseEntity<Product> responseEntity = restTemplate.getForEntity(url, Product.class, 101);
    System.out.println(responseEntity);
    Assert.isTrue(responseEntity.getStatusCode().equals(HttpStatus.OK), "get_product2 请求不成功");
    Assert.notNull(responseEntity.getBody().getId(), "get_product2  传递参数不成功");

	    //方式二:将请求参数以键值对形式存储到 Map 集合中,用于请求时URL上的拼接
    Map<String, Object> uriVariables = new HashMap<>();
    uriVariables.put("id", 101);
    Product result = restTemplate.getForObject(url, Product.class, uriVariables);
    System.out.println(result);
    Assert.notNull(result.getId(), "get_product2  传递参数不成功");
}

Нормальные результаты работы следующие:

...
<200,Product{id='101', name='ProductC', price='6666.0'},[Content-Type:"application/json;charset=UTF-8", Transfer-Encoding:"chunked", Date:"Fri, 10 May 2019 14:53:41 GMT"]>
...
Product{id='101', name='ProductC', price='6666.0'}
...

POST-запрос

Узнайте, как использоватьRestTemplateПосле того, как API отправит запрос GET, давайте посмотрим, как использовать запрос POST, который также очень распространен. Из-за типа содержимого данных запроса POSTContent-TypeОтличие в том, что случаев отправки POST-запросов относительно больше, здесь мы используем общеупотребительныйapplication/x-www-form-urlencodedиapplication/jsonЭти два типа содержимого являются примерами.

  • ОтправитьContent-Typeзаapplication/x-www-form-urlencodedPOST-запрос:

    @Test
    public void testPost_product1() {
        String url = "http://localhost:8080/product/post_product1";
    	Product product = new Product(201, "Macbook", BigDecimal.valueOf(10000));
    	  // 设置请求的 Content-Type 为 application/x-www-form-urlencoded
        MultiValueMap<String, String> header = new LinkedMultiValueMap();
        header.add(HttpHeaders.CONTENT_TYPE, (MediaType.APPLICATION_FORM_URLENCODED_VALUE));
        
        //方式二: 将请求参数值以 K=V 方式用 & 拼接,发送请求使用
        String productStr = "id=" + product.getId() + "&name=" + product.getName() + "&price=" + product.getPrice();
        HttpEntity<String> request = new HttpEntity<>(productStr, header);
        ResponseEntity<String> exchangeResult = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
        System.out.println("post_product1: " + exchangeResult);
        Assert.isTrue(exchangeResult.getStatusCode().equals(HttpStatus.OK), "post_product1 请求不成功");
    
        //方式一: 将请求参数以键值对形式存储在 MultiValueMap 集合,发送请求时使用
        MultiValueMap<String, Object> map = new LinkedMultiValueMap();
        map.add("id", (product.getId()));
        map.add("name", (product.getName()));
        map.add("price", (product.getPrice()));
        HttpEntity<MultiValueMap> request2 = new HttpEntity<>(map, header);
        ResponseEntity<String> exchangeResult2 = restTemplate.exchange(url, HttpMethod.POST, request2, String.class);
        System.out.println("post_product1: " + exchangeResult2);
        Assert.isTrue(exchangeResult.getStatusCode().equals(HttpStatus.OK), "post_product1 请求不成功");
    }
    

    Соответствующий выходной журнал выглядит следующим образом:

    ...
    post_product1: <200,Product{id='201', name='Macbook', price='10000'},[Content-Type:"text/plain;charset=UTF-8", Content-Length:"48", Date:"Fri, 10 May 2019 16:07:43 GMT"]>
    ...
    post_product1: <200,Product{id='201', name='Macbook', price='10000'},[Content-Type:"text/plain;charset=UTF-8", Content-Length:"48", Date:"Fri, 10 May 2019 16:07:43 GMT"]>
    
  • ОтправитьContent-Typeзаapplication/jsonPOST-запрос:

    @Test
    public void testPost_product2() {
        String url = "http://localhost:8080/product/post_product2";
        
       	// 设置请求的 Content-Type 为 application/json
        MultiValueMap<String, String> header = new LinkedMultiValueMap();
        header.put(HttpHeaders.CONTENT_TYPE, Arrays.asList(MediaType.APPLICATION_JSON_VALUE));
        // 设置 Accept 向服务器表明客户端可处理的内容类型
        header.put(HttpHeaders.ACCEPT, Arrays.asList(MediaType.APPLICATION_JSON_VALUE));
        // 直接将实体 Product 作为请求参数传入,底层利用 Jackson 框架序列化成 JSON 串发送请求
        HttpEntity<Product> request = new HttpEntity<>(new Product(2, "Macbook", BigDecimal.valueOf(10000)), header);
        ResponseEntity<String> exchangeResult = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
        System.out.println("post_product2: " + exchangeResult);
        Assert.isTrue(exchangeResult.getStatusCode().equals(HttpStatus.OK), "post_product2 请求不成功");
    }
    

    Выходной журнал проверки выглядит следующим образом:

    ···
    post_product2: <200,Product{id='2', name='Macbook', price='10000'},[Content-Type:"application/json;charset=UTF-8", Content-Length:"46", Date:"Fri, 10 May 2019 16:09:11 GMT"]>
    ···
    

УДАЛИТЬ запрос и запрос PUT

Запрос DELETE и запрос PUT — это два типа методов запроса RESTful, но они обычно не используются. Это просто демонстрация. Конкретный код выглядит следующим образом:

// DELETE 方法请求
@Test
public void testDelete() {
   String url = "http://localhost:8080/product/delete/{id}";
   restTemplate.delete(url, 101);
}

// PUT 方法请求
@Test
public void testPut() {
    String url = "http://localhost:8080/product/update";
    Map<String, ?> variables = new HashMap<>();
    MultiValueMap<String, String> header = new LinkedMultiValueMap();
    header.put(HttpHeaders.CONTENT_TYPE, Arrays.asList(MediaType.APPLICATION_FORM_URLENCODED_VALUE));
    Product product = new Product(101, "iWatch", BigDecimal.valueOf(2333));
    String productStr = "id=" + product.getId() + "&name=" + product.getName() + "&price=" + product.getPrice();
    HttpEntity<String> request = new HttpEntity<>(productStr, header);
    restTemplate.put(url, request);
}

загрузить файлы

Теперь давайте попробуем еще раз, как использоватьRestTemplateAPI для загрузки файлов тоже относительно простое, для начала посмотрим на код реализации:

@Test
public void testUploadFile() {
    String url = "http://localhost:8080/product/upload";
    MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
    FileSystemResource file = new FileSystemResource(new File("/Users/One/Desktop/b.txt"));
    body.add("file", file);

    MultiValueMap<String, String> header = new LinkedMultiValueMap();
    header.put(HttpHeaders.CONTENT_TYPE, Arrays.asList(MediaType.MULTIPART_FORM_DATA_VALUE));
    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, header);
    ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, requestEntity, String.class);
    System.out.println("upload: " + responseEntity);
    Assert.isTrue(responseEntity.getStatusCode().equals(HttpStatus.OK), "upload 请求不成功");
}

Если вам нужно загрузить данные типа файла, вы можете использовать только запрос POST с типом содержимогоmultipart/form-data, вам нужно вручную датьHeaderуказать этоContent-Type. Файлы, которые необходимо загрузить, можноFileSystemResourceИнкапсуляция объекта, представляющего файловый ресурс, и сервер должен использоватьMultipartRequestобъект для получения данных файла. В сочетании с работающей веб-службой запуск описанного выше метода тестирования может привести к следующему выводу журнала:

...
upload: <200,upload success filename: b.txt,[Content-Type:"text/plain;charset=UTF-8", Content-Length:"30", Date:"Fri, 10 May 2019 17:00:45 GMT"]>
...

Расширенный шаблон отдыха

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

Переключение библиотеки HTTP-запросов низкого уровня

Давайте сначала посмотрим на описание официальной документации:

The default constructor uses java.net.HttpURLConnection to perform requests. You can switch to a different HTTP library with an implementation of ClientHttpRequestFactory. There is built-in support for the following:

  • Apache HttpComponents
  • Netty
  • OkHttp

Как видно из вышеизложенногоRestTemplateИспользовать собственный JDK по умолчаниюjava.net.HttpURLConnectionВыполните запрос. Кроме того, Spring также инкапсулирует три библиотеки запросов: Apache HttpComponents, Netty и OkHttp, первую из которых мы обычно используем.HttpClientбиблиотеки, связанные с API, в то время какNettyЭто высокопроизводительная сетевая библиотека обработки запросов NIO,OkHttpЭто многофункциональная и эффективная сетевая структура, в основном используемая в программах для Android.

И мы использовали метод конструктора по умолчанию выше, чтобы создатьRestTemplateЭкземпляр, то есть с использованием собственного сетевого API JDK. Чтобы переключиться, просто введите конкретныйClientHttpRequestFactoryПросто реализуйте класс, следующий код:

RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

мы смотримRestTemplateИсходный код не найден, по умолчанию используется JDK.HttpURLConnectionКод API приведен согласно предыдущемуRestTemplateПосмотрите диаграмму иерархии классов, вы можете найти ее в родительском классе.HttpAccessorСледующий код можно найти на:

public abstract class HttpAccessor {
	// ...
	private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
	// ...
}

И заводской класс SpringSimpleClientHttpRequestFactoryописан как:implementation that uses standard JDK facilities, который также иллюстрирует построение по умолчаниюRestTemplateЭкземпляры ведут себя напрямую, используя сетевые API JDK.

настройка времени ожидания запроса

Обычно мы настраиваем поведение выполнения класса HTTP-запроса, например настройку времени ожидания вызова, ограничение времени соединения и т. д., и используем значение по умолчанию.HttpURLConnectionВ стандартной конфигурации отSimpleClientHttpRequestFactoryКласс исходного кода может видеть, что нет ограничения по времени ожидания, что означает бесконечное ожидание ответа на запрос:

// RestTemplate 默认超时设置
...
private int connectTimeout = -1;
private int readTimeout = -1;
...

Итак, как нам настроить тайм-аут, вы можете обратиться к следующему коду:

RestTemplate customRestTemplate = new RestTemplate(getClientHttpRequestFactory());

private SimpleClientHttpRequestFactory getClientHttpRequestFactory() {
    SimpleClientHttpRequestFactory clientHttpRequestFactory
            = new SimpleClientHttpRequestFactory();
    // 连接超时设置 10s
    clientHttpRequestFactory.setConnectTimeout(10_000);

    // 读取超时设置 10s
    clientHttpRequestFactory.setReadTimeout(10_000);
    return clientHttpRequestFactory;
}

Если вы хотите настроитьHttpComponentsClientДля настройки тайм-аута вы можете обратиться к статьеresttemplate-timeout-example. Конечно, кроме установки времени таймаута, есть еще параметры для настройки, которые здесь не указаны, вы можете обратиться к статьеresttemplate-httpclient-java-configдальнейшее обучение.

мы здесьRestTemplateИсследование подошло к концу, если вам интересно, вы можете дополнительно изучить соответствующий исходный код и иметь возможность попробовать его. 😁

использованная литература

У-у-у. Бросай арлингтон-терьера.com/rest-temp...  

блог Brother space.com/spring-boot…

Уууууууу.Поставь арлингтон терьера.com/spring-rest…

Ууху. Call.com/question/28…

как это сделать на java.com/spring-boot…

docs.spring.IO/весна/документы…

en.wikipedia.org/wiki/Presentation-Layer State Transfer…

docs.spring.IO/spring-без оперативной памяти…