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错误都会报异常。

posted @ 2020-12-23 20:29  ralgo  阅读(1170)  评论(0)    收藏  举报