java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated

最近项目中利用httpclient时,访问接口报错。错误信息如下:
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated_第1张图片
错误原因分析:
并发调用同一个httpclient去请求数据导致,当上一个post|get请求尚未结束时,又启新的线程再次使用该httpclient请求数据。

解决方案:
采用线程池,从线程池中获取httpclient。

这里贴出服务器访问https\http链接类型接口完整代码,
使用方法:

        String url = "**/**/**/setCustomerInfo";
        String xml = "*****";
		Map<String, String> param = new HashMap<>();
		param.put("sb", xml);
		String results = SSLHttpHelper.getHelper().post(url, param);
		JSONObject jsonObject = new JSONObject(results);
		// 解析返回的xml
		if (!(jsonObject.get("result").toString().equals("false"))) {
			Document docData = DocumentHelper.parseText(jsonObject.get("responsMess").toString());
			Element rootElt = docData.getRootElement();
			Element element = rootElt.element("Body").element("SyncCustomerInfoResponse").element("SyncCustomerInfoResult");
			String text = element.getText();
			JSONObject data = new JSONObject(text);
			return data;
		}

SSLHttpHelper.java

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import org.apache.commons.collections.MapUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
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.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

public class SSLHttpHelper {
	// 创建HostnameVerifier
	// 用于解决javax.net.ssl.SSLException: hostname in certificate didn't match:
	static HostnameVerifier hostnameVerifier = new HostnameVerifier() {
		@Override
		public boolean verify(String s, SSLSession sslSession) {
			return true;
		}
	};
	private static SSLHttpHelper instance = new SSLHttpHelper();

	public static SSLHttpHelper getHelper() {
		return instance;
	}

	private static CloseableHttpClient httpsClient = null;
	private static CloseableHttpClient httpClient = null;
	static {
		httpClient = getHttpClient();
		httpsClient = getHttpsClient();
	}
    //利用PoolManager获取连接
	public static CloseableHttpClient getHttpClient() {
		try {
			httpClient = HttpClients.custom().setConnectionManager(PoolManager.getHttpPoolInstance())
					.setConnectionManagerShared(true).setDefaultRequestConfig(requestConfig())
					.setRetryHandler(retryHandler()).build();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return httpClient;
	}
    //利用PoolsManager获取连接
	public static CloseableHttpClient getHttpsClient() {
		try {
			SSLContext ctx = SSLContext.getInstance("SSL");
			TrustManager[] trustAllCerts = { new TrustAllTrustManager() };
			ctx.init(null, trustAllCerts, null);
			ConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(ctx, hostnameVerifier);
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
					.register("http", PlainConnectionSocketFactory.INSTANCE).register("https", connectionSocketFactory)
					.build();
			// 设置连接池
			httpsClient = HttpClients.custom()
					.setConnectionManager(PoolsManager.getHttpsPoolInstance(socketFactoryRegistry))
					.setConnectionManagerShared(true).setDefaultRequestConfig(requestConfig())
					.setRetryHandler(retryHandler()).build();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return httpsClient;
	}

	// 配置请求的超时设置
	// 首先设置全局的标准cookie策略
	public static RequestConfig requestConfig() {
		RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT)
				.setConnectionRequestTimeout(20000).setConnectTimeout(20000).setSocketTimeout(20000).build();
		return requestConfig;
	}

	public static HttpRequestRetryHandler retryHandler() {
		// 请求重试处理
		HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
			public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
				if (executionCount >= 5) {// 如果已经重试了5次,就放弃
					return false;
				}
				if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试
					return true;
				}
				if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常
					return false;
				}
				if (exception instanceof InterruptedIOException) {// 超时
					return false;
				}
				if (exception instanceof UnknownHostException) {// 目标服务器不可达
					return false;
				}
				if (exception instanceof ConnectTimeoutException) {// 连接被拒绝
					return false;
				}
				if (exception instanceof SSLException) {// ssl握手异常
					return false;
				}

				HttpClientContext clientContext = HttpClientContext.adapt(context);
				HttpRequest request = clientContext.getRequest();
				// 如果请求是幂等的,就再次尝试
				if (!(request instanceof HttpEntityEnclosingRequest)) {
					return true;
				}
				return false;
			}
		};
		return httpRequestRetryHandler;
	}

	

	public String post(String httpUrl, Map<String, String> request) {
		String result = "";
		CloseableHttpClient httpClient = getHttpClient();
		try {
			HttpPost httpPost = new HttpPost(httpUrl);
			if(!MapUtils.isEmpty(request)){
				List<NameValuePair> nvps = new ArrayList<NameValuePair>();
				for (Iterator<Map.Entry<String, String>> iterator = request.entrySet().iterator(); iterator.hasNext();) {
					Map.Entry<String, String> entry = iterator.next();
					nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
				httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
			}
			CloseableHttpResponse response = httpsClient.execute(httpPost);
			result = EntityUtils.toString(response.getEntity());
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	
	public String httpPost(String httpUrl, Map<String, String> request) {
		String result = "";
		CloseableHttpClient httpClient = getHttpClient();
		try {
			HttpPost httpPost = new HttpPost(httpUrl);
			if(!MapUtils.isEmpty(request)){
				List<NameValuePair> nvps = new ArrayList<NameValuePair>();
				for (Iterator<Map.Entry<String, String>> iterator = request.entrySet().iterator(); iterator.hasNext();) {
					Map.Entry<String, String> entry = iterator.next();
					nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
				httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
			}
			CloseableHttpResponse response = httpClient.execute(httpPost);
			result = EntityUtils.toString(response.getEntity());
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	//连接池
	public static class PoolManager {
		public static PoolingHttpClientConnectionManager clientConnectionManager = null;
		private static int maxTotal = 200;
		private static int defaultMaxPerRoute = 100;

		private PoolManager() {
			clientConnectionManager.setMaxTotal(maxTotal);
			clientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
		}

		private static class PoolManagerHolder {
			public static PoolManager instance = new PoolManager();
		}

		public static PoolManager getInstance() {
			if (null == clientConnectionManager)
				clientConnectionManager = new PoolingHttpClientConnectionManager();
			return PoolManagerHolder.instance;
		}

		public static PoolingHttpClientConnectionManager getHttpPoolInstance() {
			PoolManager.getInstance();
			return PoolManager.clientConnectionManager;
		}

	}
    //连接池
	public static class PoolsManager {
		public static PoolingHttpClientConnectionManager clientConnectionManager = null;
		private static int maxTotal = 200;
		private static int defaultMaxPerRoute = 100;

		private PoolsManager() {
			clientConnectionManager.setMaxTotal(maxTotal);
			clientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
		}

		private static class PoolsManagerHolder {
			public static PoolsManager instance = new PoolsManager();
		}

		public static PoolsManager getInstance(Registry<ConnectionSocketFactory> socketFactoryRegistry) {
			if (null == clientConnectionManager)
				clientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
			return PoolsManagerHolder.instance;
		}

		public static PoolingHttpClientConnectionManager getHttpsPoolInstance(Registry<ConnectionSocketFactory> socketFactoryRegistry) {
			PoolsManager.getInstance(socketFactoryRegistry);
			return PoolsManager.clientConnectionManager;
		}
	}
}

TrustAllTrustManager.java

public class TrustAllTrustManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {

	@Override
	public java.security.cert.X509Certificate[] getAcceptedIssuers() {
		return null;
	}

	@Override
	public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
			throws java.security.cert.CertificateException {
		return;
	}

	@Override
	public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
			throws java.security.cert.CertificateException {
		return;
	}
}

你可能感兴趣的:(Java,java)