spring boot 整合 HttpClient实现线程池连接

1.HttpClient介绍

HTTP 协议是现在 Internet 上使用得最多、最重要的协议,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。

2.SpringBoot整合HttpClient

2.1.导入jar包

5.0后开始出现异步,要使用这两个Jar包

<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
</dependency>
<!-- httpClient文件上传需要 -->
<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpmime</artifactId>
</dependency

2.2 配置文件httpclient.properties

#最大连接数
http_max_total= 1000
#并发数
http_default_max_perRoute = 80
#创建连接的最长时间
http_validate_after_inactivity=5000
#从连接池中获取到连接的最长时间
http_connection_request_timeout=500
http_connection_timeout = 10000
#数据传输的最长时间
http.socketTimeout=10000
waitTime = 30000
idleConTime = 3
retryCount = 3

2.3 配置类

@Configuration	//注解--配置类
@PropertySource(value="classpath:/properties/httpClient.properties")
package com.123.lenovo.adapter.se.config;
 
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
 
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.Build;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import com.123.lenovo.adapter.se.common.IdleConnectionEvictor;
 
@Configuration
public class HttpClientConfig {
 
	@Value("${http_max_total}")
	private int maxTotal = 800;
	
	@Value("${http_default_max_perRoute}")
	private int defaultMaxPerRoute = 80;
	
	@Value("${http_validate_after_inactivity}")
	private int validateAfterInactivity = 1000;
	
	@Value("${http_connection_request_timeout}")
	private int connectionRequestTimeout = 5000;
	
	@Value("${http_connection_timeout}")
	private int connectTimeout = 10000;
	
	@Value("${http_socket_timeout}")
	private int socketTimeout = 20000;
	
	@Value("${waitTime}")
	private int waitTime = 30000;
	
	@Value("${idleConTime}")
	private int idleConTime = 3;
	
	@Value("${retryCount}")
	private int retryCount = 3;
	
	@Bean
	public PoolingHttpClientConnectionManager createPoolingHttpClientConnectionManager() {
		PoolingHttpClientConnectionManager poolmanager = new PoolingHttpClientConnectionManager();
		poolmanager.setMaxTotal(maxTotal);
		poolmanager.setDefaultMaxPerRoute(defaultMaxPerRoute);
		poolmanager.setValidateAfterInactivity(validateAfterInactivity);
		return poolmanager;
	}
	
	@Bean
	public CloseableHttpClient createHttpClient(PoolingHttpClientConnectionManager poolManager) {
		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().setConnectionManager(poolManager);
		httpClientBuilder.setKeepAliveStrategy(new ConnectionKeepAliveStrategy() {
			
			@Override
			public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
				HeaderElementIterator iterator = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
				while (iterator.hasNext()) {
					HeaderElement headerElement = iterator.nextElement();
					String param = headerElement.getName();
					String value = headerElement.getValue();
					if (null != value && param.equalsIgnoreCase("timeout")) {
						return Long.parseLong(value) * 1000;
					}
				}
				return 30 * 1000;
			}
		});
		httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, false));
		return httpClientBuilder.build();
	}
	
	@Bean
	public SSLContext createSSLContext() throws Exception {
		return SSLContexts.custom().loadTrustMaterial(KeyStore.getInstance(KeyStore.getDefaultType()), new TrustAllStrategy()).build();
	}
	
	@Bean
	public SSLConnectionSocketFactory createSSLConnectionSocketFactory(SSLContext sslContext) {
		return new SSLConnectionSocketFactory(sslContext,
				new String[] { "TLSv1" },
                null,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier());
	}
	
	@Bean
	public RequestConfig createRequestConfig() {
		return RequestConfig.custom()
				.setConnectionRequestTimeout(connectionRequestTimeout) 	// 从连接池中取连接的超时时间
				.setConnectTimeout(connectTimeout)						// 连接超时时间
				.setSocketTimeout(socketTimeout)						// 请求超时时间
				.build();
	}
	
	@Bean
	public IdleConnectionEvictor createIdleConnectionEvictor(PoolingHttpClientConnectionManager poolManager) {
		IdleConnectionEvictor idleConnectionEvictor = new IdleConnectionEvictor(poolManager, waitTime, idleConTime);
		return idleConnectionEvictor;
	}
	
}

2.4 创建httpClient的工具类

@Component
public class HttpClientHelper {
	
	private Logger LOGGER = LoggerFactory.getLogger(HttpClientHelper.class);
	
	@Autowired
	private CloseableHttpClient httpClient;
	
	@Autowired
	private RequestConfig requestConfig;
	
	public String get(String url, HashMap<String, Object> paramMap, HashMap<String, Object> header) {
		String result = null;
		if ("".equals(url)) {
			return result;
		}
		// 创建一个request对象
		HttpGet httpGet = new HttpGet(url);
		CloseableHttpResponse response = null;
		try {
			// 配置连接参数
			httpGet.setConfig(requestConfig);
			//设置参数  
			if (paramMap != null && paramMap.size() > 0) {
				List<NameValuePair> params = new ArrayList<>();
				for (Entry<String, Object> entry : paramMap.entrySet()) {
					params.add(new BasicNameValuePair(entry.getKey(), URLEncoder.encode(entry.getValue().toString(), "UTF-8")));
				}
				String strParams = EntityUtils.toString(new UrlEncodedFormEntity(params));
				// 防止多参数时,分隔符","被转义
				String realParams = URLDecoder.decode(strParams, "UTF-8");
				httpGet.setURI(new URI(httpGet.getURI().toString().indexOf("?") > 0 ? httpGet.getURI().toString() + "&" + realParams : httpGet.getURI().toString() + "?" + realParams));
			}
			// 设置头
			if (header != null && header.size() > 0) {
				for (Entry<String, Object> entry : header.entrySet()) {
					httpGet.addHeader(entry.getKey(), entry.getValue().toString());
				}
			}
			// 执行request请求
			response = httpClient.execute(httpGet);
			result = parseResponse(response);
			
		} catch (Exception e) {
			LOGGER.error("url : "+ url +", msg : " + e.getMessage());
			httpGet.abort();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	public String post(String url, HashMap<String, Object> paramMap, HashMap<String, Object> header) {
		String result = null;
		if ("".equals(url)) {
			return result;
		}
		// 创建一个request对象
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try {
			// 配置连接参数
			httpPost.setConfig(requestConfig);
			// 设置参数
			if (paramMap != null && paramMap.size() > 0) {
				List<NameValuePair> params = new ArrayList<>();
				for (Entry<String, Object> entry : paramMap.entrySet()) {
					params.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
				}
				HttpEntity entity = new UrlEncodedFormEntity(params);
				httpPost.setEntity(entity);
			}
			// 设置头
			if (header != null && header.size() > 0) {
				for (Entry<String, Object> entry : header.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue().toString());
				}
			}
			// 执行request请求
			response = httpClient.execute(httpPost);
			result = reponseHandle(response);
		} catch (Exception e) {
			LOGGER.error("url : "+ url +", msg : " + e.getMessage());
			httpPost.abort();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	public String postJSON(String url, String json_str, HashMap<String, Object> header) {
		String result = null;
		if ("".equals(url)) {
			return result;
		}
		// 创建一个request对象
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try {
			// 配置连接参数
			httpPost.setConfig(requestConfig);
			// 设置参数
			if (json_str != null && !"".equals(json_str)) {
				StringEntity entity = new StringEntity(json_str, ContentType.APPLICATION_JSON);
				entity.setContentEncoding("UTF-8");    
				entity.setContentType("application/json");
				httpPost.setEntity(entity);
			}
			// 设置头
			if (header != null && header.size() > 0) {
				for (Entry<String, Object> entry : header.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue().toString());
				}
			}
			// 执行request请求
			response = httpClient.execute(httpPost);
			result = reponseHandle(response);
			
		} catch (Exception e) {
			LOGGER.error("url : "+ url +", msg : " + e.getMessage()+", param : " +json_str);
			httpPost.abort();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	public String uploadFile(String url, String filePath, String fileParam, Map<String, Object> params) {
		File file = new File(filePath);
		if (!(file.exists() && file.isFile())) {
			throw new RuntimeException("file : file is null");
		}
		String result = null;
		if ("".equals(url)) {
			return result;
		}
		// 创建一个request对象
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try {
			// 配置连接参数
			httpPost.setConfig(requestConfig);
			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
			builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
			builder.addBinaryBody(fileParam, file, ContentType.DEFAULT_BINARY, file.getName());
			if (params != null && params.size() > 0) {
				for (Entry<String, Object> entry : params.entrySet()) {
					builder.addTextBody(entry.getKey(), entry.getValue().toString(), ContentType.create("text/plain", Consts.UTF_8));
				}
			}
			HttpEntity requestEntity = builder.build();
			httpPost.setEntity(requestEntity);
			// 执行request请求
			response = httpClient.execute(httpPost);
			result = reponseHandle(response);
			
		} catch (Exception e) {
			httpPost.abort();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	/**
	 * 解析 response数据
	 * @description
	 * @param response
	 * @return
	 * @author tangjingjing
	 * @date 2018年10月12日
	 */
	private String parseResponse(CloseableHttpResponse response) {
		String result = "";
		// 获取响应体
		HttpEntity httpEntity = null;
		InputStream inputStream = null;
		try {
			// 获取响应状态
			int statusCode = response.getStatusLine().getStatusCode();
			// 没有正常响应
			if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) {
				throw new RuntimeException("statusCode : " + statusCode);
			}
			// 获取响应体
			httpEntity = response.getEntity();
			if (httpEntity != null) {
				inputStream = httpEntity.getContent();
				BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
				StringBuffer sb = new StringBuffer();
	            String line = "";
	            while((line=reader.readLine())!=null){
	                sb.append(line);
	            }
	            reader.close();
	            result = sb.toString();
			}
 
		} catch (Exception e) {
			LOGGER.error("HttpClientHelper parseResponse error", e);
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			// 如果httpEntity没有被完全消耗,那么连接无法安全重复使用,将被关闭并丢弃
			try {
				EntityUtils.consume(httpEntity);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	private String reponseHandle(CloseableHttpResponse response) {
		String result = "";
		// 获取响应体
		HttpEntity httpEntity = null;
		try {
			// 获取响应状态
			int statusCode = response.getStatusLine().getStatusCode();
			// 没有正常响应
			if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) {
				throw new RuntimeException("statusCode : " + statusCode);
			}
			// 获取响应体
			httpEntity = response.getEntity();
			if (httpEntity !=null) {
				result = EntityUtils.toString(httpEntity);
			}
			
		} catch (Exception e) {
			LOGGER.error("HttpClientHelper reponseHandle error", e);
		} finally {
			// 如果httpEntity没有被完全消耗,那么连接无法安全重复使用,将被关闭并丢弃
			try {
				EntityUtils.consume(httpEntity);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
}

2.5 创建HttpClient无效连接清除类

@Component
public class HttpClientHelper {
	
	private Logger LOGGER = LoggerFactory.getLogger(HttpClientHelper.class);
	
	@Autowired
	private CloseableHttpClient httpClient;
	
	@Autowired
	private RequestConfig requestConfig;
	
	public String get(String url, HashMap<String, Object> paramMap, HashMap<String, Object> header) {
		String result = null;
		if ("".equals(url)) {
			return result;
		}
		// 创建一个request对象
		HttpGet httpGet = new HttpGet(url);
		CloseableHttpResponse response = null;
		try {
			// 配置连接参数
			httpGet.setConfig(requestConfig);
			//设置参数  
			if (paramMap != null && paramMap.size() > 0) {
				List<NameValuePair> params = new ArrayList<>();
				for (Entry<String, Object> entry : paramMap.entrySet()) {
					params.add(new BasicNameValuePair(entry.getKey(), URLEncoder.encode(entry.getValue().toString(), "UTF-8")));
				}
				String strParams = EntityUtils.toString(new UrlEncodedFormEntity(params));
				// 防止多参数时,分隔符","被转义
				String realParams = URLDecoder.decode(strParams, "UTF-8");
				httpGet.setURI(new URI(httpGet.getURI().toString().indexOf("?") > 0 ? httpGet.getURI().toString() + "&" + realParams : httpGet.getURI().toString() + "?" + realParams));
			}
			// 设置头
			if (header != null && header.size() > 0) {
				for (Entry<String, Object> entry : header.entrySet()) {
					httpGet.addHeader(entry.getKey(), entry.getValue().toString());
				}
			}
			// 执行request请求
			response = httpClient.execute(httpGet);
			result = parseResponse(response);
			
		} catch (Exception e) {
			LOGGER.error("url : "+ url +", msg : " + e.getMessage());
			httpGet.abort();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	public String post(String url, HashMap<String, Object> paramMap, HashMap<String, Object> header) {
		String result = null;
		if ("".equals(url)) {
			return result;
		}
		// 创建一个request对象
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try {
			// 配置连接参数
			httpPost.setConfig(requestConfig);
			// 设置参数
			if (paramMap != null && paramMap.size() > 0) {
				List<NameValuePair> params = new ArrayList<>();
				for (Entry<String, Object> entry : paramMap.entrySet()) {
					params.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
				}
				HttpEntity entity = new UrlEncodedFormEntity(params);
				httpPost.setEntity(entity);
			}
			// 设置头
			if (header != null && header.size() > 0) {
				for (Entry<String, Object> entry : header.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue().toString());
				}
			}
			// 执行request请求
			response = httpClient.execute(httpPost);
			result = reponseHandle(response);
		} catch (Exception e) {
			LOGGER.error("url : "+ url +", msg : " + e.getMessage());
			httpPost.abort();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	public String postJSON(String url, String json_str, HashMap<String, Object> header) {
		String result = null;
		if ("".equals(url)) {
			return result;
		}
		// 创建一个request对象
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try {
			// 配置连接参数
			httpPost.setConfig(requestConfig);
			// 设置参数
			if (json_str != null && !"".equals(json_str)) {
				StringEntity entity = new StringEntity(json_str, ContentType.APPLICATION_JSON);
				entity.setContentEncoding("UTF-8");    
				entity.setContentType("application/json");
				httpPost.setEntity(entity);
			}
			// 设置头
			if (header != null && header.size() > 0) {
				for (Entry<String, Object> entry : header.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue().toString());
				}
			}
			// 执行request请求
			response = httpClient.execute(httpPost);
			result = reponseHandle(response);
			
		} catch (Exception e) {
			LOGGER.error("url : "+ url +", msg : " + e.getMessage()+", param : " +json_str);
			httpPost.abort();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	public String uploadFile(String url, String filePath, String fileParam, Map<String, Object> params) {
		File file = new File(filePath);
		if (!(file.exists() && file.isFile())) {
			throw new RuntimeException("file : file is null");
		}
		String result = null;
		if ("".equals(url)) {
			return result;
		}
		// 创建一个request对象
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try {
			// 配置连接参数
			httpPost.setConfig(requestConfig);
			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
			builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
			builder.addBinaryBody(fileParam, file, ContentType.DEFAULT_BINARY, file.getName());
			if (params != null && params.size() > 0) {
				for (Entry<String, Object> entry : params.entrySet()) {
					builder.addTextBody(entry.getKey(), entry.getValue().toString(), ContentType.create("text/plain", Consts.UTF_8));
				}
			}
			HttpEntity requestEntity = builder.build();
			httpPost.setEntity(requestEntity);
			// 执行request请求
			response = httpClient.execute(httpPost);
			result = reponseHandle(response);
			
		} catch (Exception e) {
			httpPost.abort();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	/**
	 * 解析 response数据
	 * @description
	 * @param response
	 * @return
	 * @author tangjingjing
	 * @date 2018年10月12日
	 */
	private String parseResponse(CloseableHttpResponse response) {
		String result = "";
		// 获取响应体
		HttpEntity httpEntity = null;
		InputStream inputStream = null;
		try {
			// 获取响应状态
			int statusCode = response.getStatusLine().getStatusCode();
			// 没有正常响应
			if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) {
				throw new RuntimeException("statusCode : " + statusCode);
			}
			// 获取响应体
			httpEntity = response.getEntity();
			if (httpEntity != null) {
				inputStream = httpEntity.getContent();
				BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
				StringBuffer sb = new StringBuffer();
	            String line = "";
	            while((line=reader.readLine())!=null){
	                sb.append(line);
	            }
	            reader.close();
	            result = sb.toString();
			}
 
		} catch (Exception e) {
			LOGGER.error("HttpClientHelper parseResponse error", e);
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			// 如果httpEntity没有被完全消耗,那么连接无法安全重复使用,将被关闭并丢弃
			try {
				EntityUtils.consume(httpEntity);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	private String reponseHandle(CloseableHttpResponse response) {
		String result = "";
		// 获取响应体
		HttpEntity httpEntity = null;
		try {
			// 获取响应状态
			int statusCode = response.getStatusLine().getStatusCode();
			// 没有正常响应
			if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) {
				throw new RuntimeException("statusCode : " + statusCode);
			}
			// 获取响应体
			httpEntity = response.getEntity();
			if (httpEntity !=null) {
				result = EntityUtils.toString(httpEntity);
			}
			
		} catch (Exception e) {
			LOGGER.error("HttpClientHelper reponseHandle error", e);
		} finally {
			// 如果httpEntity没有被完全消耗,那么连接无法安全重复使用,将被关闭并丢弃
			try {
				EntityUtils.consume(httpEntity);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
}

说明,这定时器清除是通过构造类定时清除的,是在定义配置文件Bean的时候就已经调用了
另外使用合适的连接数要根据有多少并发量来合理的测试使用的线程数是多少

你可能感兴趣的:(java,spring,boot,后端,java)