java:HTTP连接池,设置代理

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


前言

在多线程,或者某些特定业务场景时,我们需要频繁创建http请求,对于多次请求会造成内存压力以及异常抛出。本文利用spring自带的​​RestTemplate​​​来创建使用连接池
​参考链接:​​

配置类

注:不使用代理可以删除.setProxy(proxy)方法即可,也可以直接注释第85行代码

package com.picc.web.utils;

import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.context.properties.ConfigurationProperties;
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.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.util.List;

/**
* HttpClient的配置类---类似工具类
* Configuration:标明这是一个配置类
* ConfigurationProperties:加载application.properties属性文件
* prefix:前缀
* ignoreUnknownFields:忽略找不到的属性
* 自动将属性文件中的值赋值该类中的属性
*
* 最终需要知道:
* 1 SpringBoot推荐使用RestTemplate操作RestFul API
* 2 RestTemplate底层需要借助HttpClient创建
*
*
*/
@Configuration
//@ConfigurationProperties(prefix = "http", ignoreUnknownFields = true)
public class HttpClientConfig {

private Integer maxTotal=300;// 最大连接

private Integer defaultMaxPerRoute=320;// 每个host的最大连接

private Integer connectTimeout=5000;// 连接超时时间

private Integer connectionRequestTimeout=5000;// 请求超时时间

private Integer socketTimeout=5000;// 响应超时时间
//代理IP
static String host = "127.0.0.1";
//代理端口
static int port = 8088;
/**
* HttpClient连接池
* @return
*/
@Bean
public HttpClientConnectionManager httpClientConnectionManager() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(maxTotal);
connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
return connectionManager;
}

/**
* 注册RequestConfig
* @return
*/
@Bean
public RequestConfig requestConfig() {
return RequestConfig.custom().setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout)
.build();
}

/**
* 注册HttpClient
* @param manager
* @param config
* @return
*/
@Bean
public HttpClient httpClient(HttpClientConnectionManager manager, RequestConfig config) {
HttpHost proxy = null;
try {
proxy = new HttpHost(host, port, "http");
} catch (Exception e) {
e.printStackTrace();
}
return HttpClientBuilder.create().setConnectionManager(manager).setDefaultRequestConfig(config).setProxy(proxy)
.build();
}
/**
* 使用连接池管理连接
* @param httpClient
* @return
*/
@Bean
public ClientHttpRequestFactory requestFactory(HttpClient httpClient) {
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
/**
* 使用HttpClient来初始化一个RestTemplate
* @param requestFactory
* @return
*/
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
RestTemplate template = new RestTemplate(requestFactory);

List<HttpMessageConverter<?>> list = template.getMessageConverters();
for (HttpMessageConverter<?> mc : list) {
if (mc instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) mc).setDefaultCharset(Charset.forName("UTF-8"));
}
}
return template;
}

public Integer getMaxTotal() {
return maxTotal;
}

public void setMaxTotal(Integer maxTotal) {
this.maxTotal = maxTotal;
}

public Integer getDefaultMaxPerRoute() {
return defaultMaxPerRoute;
}

public void setDefaultMaxPerRoute(Integer defaultMaxPerRoute) {
this.defaultMaxPerRoute = defaultMaxPerRoute;
}

public Integer getConnectTimeout() {
return connectTimeout;
}

public void setConnectTimeout(Integer connectTimeout) {
this.connectTimeout = connectTimeout;
}

public Integer getConnectionRequestTimeout() {
return connectionRequestTimeout;
}

public void setConnectionRequestTimeout(Integer connectionRequestTimeout) {
this.connectionRequestTimeout = connectionRequestTimeout;
}

public Integer getSocketTimeout() {
return socketTimeout;
}

public void setSocketTimeout(Integer socketTimeout) {
this.socketTimeout = socketTimeout;
}
}

使用

​​关于spring容器反射获取单例可以参考这个链接博主的工具类​​ 因为交予Spring容器管理,所以在多线程中可以使用反射创建对应对象(不是多线程可以使用注入),注意请求前缀http协议头需要加

private RestTemplate bean = SpringContextUtil.getBean(RestTemplate.class);
@Override
public void run() {
ResponseEntity<String> forEntity = bean.getForEntity("http://www.baidu.com", String.class);
System.out.println(forEntity.toString());
}

代理问题

不使用代理会出一些其他错误

org.springframework.web.client.ResourceAccessException: I/O error on POST request for
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to 127.0.0.1:8088 [/127.0.0.1] failed: Connection refused: connect

请求头

针对个性化发送要加请求头可以这样

@Autowired
private RestTemplate restTemplate;

Map<String, String> map = new HashMap<>();
//个性化参数
map.put("yearMonth",ny);
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", appCode);
HttpEntity<Map> requestEntity = new HttpEntity<>(map, headers);
String post =restTemplate.postForEntity(holidayUrl,requestEntity,String.class).getBody();


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java