spring boot 整合 HttpClient

第一步:引入HttpClient 的jar包

1、 httpClient 5.0 开始支持异步(Async)请求;

2、httpclient 版本过低上传文件会出,原因是 org.apache.http.entity.ContentType 没有方法 withParameters(final NameValuePair... params);

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

第二步:创建一个httpClient的配置类

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;
	}
	
}

第三步:创建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;
	}
	
}

第四步:创建HttpClient无效连接清除类

/**
 * 定期清理无效的http连接
 * @author viruser
 *
 */
package com.123.lenovo.adapter.se.common;

import java.util.concurrent.TimeUnit;

import javax.annotation.PreDestroy;

import org.apache.http.conn.HttpClientConnectionManager;

/**
 * 定期清理无效的http连接
 * @author viruser
 *
 */
public class IdleConnectionEvictor extends Thread {

	private final HttpClientConnectionManager manager;
	
	private Integer waitTime;
	
	private Integer idleConTime;
	
	private volatile boolean shutdown = true;
	
	public IdleConnectionEvictor(HttpClientConnectionManager manager, Integer waitTime, Integer idleConTime) {
		this.manager = manager;
		this.waitTime = waitTime;
		this.idleConTime = idleConTime;
		this.start();
	}
	
	@Override
	public void run() {
		try {
			if (shutdown) {
				synchronized (this) {
					wait(waitTime);
					manager.closeIdleConnections(idleConTime, TimeUnit.SECONDS);
					// 关闭失效的连接
					manager.closeExpiredConnections();
				}
			}
		} catch (Exception e) {
			
		}
	}
	
	@PreDestroy
	public void shutdown() {
		shutdown = false;
		synchronized (this) {
			notifyAll();
		}
	}
	
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值