Spring Boot(六)RestTemplate(含HTTP连接池)
0、准备工作
本文中介绍的工程依赖Spring Boot(五)json格式的缓存,我们姑且简称它为工程A,所以在启动本文的项目之前,我们应该先启动工程A。在启动工程A成功后,打开postman,添加一个user,如下图:
另外我将本文介绍的工程成为工程B,项目A和B的关系就是B会通过http请求拿到A的响应,响应的请求体是一段代表User的json代码。
1、创建工程
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.ralgond</groupId>
<artifactId>boot-resttmp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
</parent>
<properties>
<start-class>
com.github.ralgond.bootresttmp.BootResttmpMainApp</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、工程布局如下图
3、编辑application.yml
server:
port: 7777
4、编辑User类
package com.github.ralgond.bootresttmp.entity;
public class User {
private Integer id;
private String name;
public User() {
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
5、编辑配置类RestTemplateConfig
package com.github.ralgond.bootresttmp;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
RestTemplate restTemplate() {
return new RestTemplate(httpRequestFactory());
}
// @Bean
// RestTemplate restTemplate() {
// return new RestTemplate();
// }
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
return new HttpComponentsClientHttpRequestFactory(httpClient());
}
@Bean
public HttpClient httpClient() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
//设置整个连接池最大连接数 根据自己的场景决定
connectionManager.setMaxTotal(200);
//路由是对maxTotal的细分
connectionManager.setDefaultMaxPerRoute(100);
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(10000) //服务器返回数据(response)的时间,超过该时间抛出read timeout
.setConnectTimeout(5000)//连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
.setConnectionRequestTimeout(1000)//从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
.build();
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build();
}
}
6、编辑主启动类
package com.github.ralgond.bootresttmp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.github.ralgond.bootresttmp.entity.User;
@SpringBootApplication
@RestController
public class BootResttmpMainApp {
@Autowired
RestTemplate restTemplate;
@RequestMapping(method=RequestMethod.GET, value="/user/{id}")
public User getUser(@PathVariable("id") int id) {
User user = restTemplate.getForObject("http://localhost:8888/user/"+id, User.class);
System.out.println("====>get from remote: "+user);
return user;
}
public static void main(String args[]) {
SpringApplication.run(BootResttmpMainApp.class, args);
}
}
7、启动主启动类
8、Q&A
resttemplate收到404响应是否会报异常?
会的,resttemplate遇到4xx、5xx错误都会报异常。