Authored by LUOXC

异步构建httpclient

1 package com.yohoufo.common.utils; 1 package com.yohoufo.common.utils;
2 2
  3 +import lombok.extern.slf4j.Slf4j;
3 import org.apache.http.HttpStatus; 4 import org.apache.http.HttpStatus;
4 import org.apache.http.NameValuePair; 5 import org.apache.http.NameValuePair;
5 import org.apache.http.client.config.RequestConfig; 6 import org.apache.http.client.config.RequestConfig;
@@ -34,162 +35,184 @@ import java.security.cert.X509Certificate; @@ -34,162 +35,184 @@ import java.security.cert.X509Certificate;
34 import java.util.ArrayList; 35 import java.util.ArrayList;
35 import java.util.List; 36 import java.util.List;
36 import java.util.Map; 37 import java.util.Map;
  38 +import java.util.Objects;
37 39
  40 +@Slf4j
38 @Component 41 @Component
39 public class HttpClient { 42 public class HttpClient {
40 - private Logger logger = LoggerFactory.getLogger(getClass());  
41 -  
42 - protected static final int connectionRequestTimeout = 6000;  
43 - protected static final int connectionTimeout = 3000;  
44 - protected static final int socketTimeout = 2000;  
45 -  
46 - //最大总数  
47 - private final int maxTotal = 30;  
48 -  
49 - //默认并发数  
50 - private final int defaultMaxPerRoute = 10;  
51 -  
52 - protected CloseableHttpClient httpClient;  
53 -  
54 - @PostConstruct  
55 - public void init() throws Exception{  
56 - HttpClientBuilder b = HttpClientBuilder.create();  
57 -  
58 - // setup a Trust Strategy that allows all certificates.  
59 - //  
60 - SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null,  
61 - new TrustStrategy() {  
62 - @Override  
63 - public boolean isTrusted(X509Certificate[] arg0, String arg1)  
64 - throws CertificateException {  
65 - return true;  
66 - }  
67 - }).build();  
68 - b.setSSLContext(sslContext);  
69 -  
70 - // don't check Hostnames, either.  
71 - // -- use SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if  
72 - // you don't want to weaken  
73 - HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;  
74 -  
75 - // here's the special part:  
76 - // -- need to create an SSL Socket Factory, to use our weakened  
77 - // "trust strategy";  
78 - // -- and create a Registry, to register it.  
79 - //  
80 - SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(  
81 - sslContext, hostnameVerifier);  
82 - Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder  
83 - .<ConnectionSocketFactory> create()  
84 - .register("http",  
85 - PlainConnectionSocketFactory.getSocketFactory())  
86 - .register("https", sslSocketFactory).build();  
87 -  
88 - // now, we create connection-manager using our Registry.  
89 - // -- allows multi-threaded use  
90 - PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(  
91 - socketFactoryRegistry);  
92 - connMgr.setMaxTotal(maxTotal);  
93 - connMgr.setDefaultMaxPerRoute(defaultMaxPerRoute);  
94 - b.setConnectionManager(connMgr);  
95 -  
96 - //request config  
97 - RequestConfig requestConfig = RequestConfig.custom()  
98 - .setConnectionRequestTimeout(connectionRequestTimeout)  
99 - .setConnectTimeout(connectionTimeout)  
100 - .setSocketTimeout(socketTimeout)  
101 - .build();  
102 - b.setDefaultRequestConfig(requestConfig);  
103 -  
104 - // finally, build the HttpClient;  
105 - // -- done!  
106 - httpClient = b.build();  
107 - }  
108 -  
109 - public void destroy() {  
110 - if(httpClient != null)  
111 - httpClient.getConnectionManager().shutdown();  
112 - }  
113 -  
114 - /**  
115 - * Get请求  
116 - * @param url  
117 - * @return  
118 - * @throws Exception  
119 - */  
120 - public String get(String url) throws Exception {  
121 - HttpGet httpget = new HttpGet(url); 43 + private Logger logger = LoggerFactory.getLogger(getClass());
  44 +
  45 + protected static final int connectionRequestTimeout = 6000;
  46 + protected static final int connectionTimeout = 3000;
  47 + protected static final int socketTimeout = 2000;
  48 +
  49 + //最大总数
  50 + private final int maxTotal = 30;
  51 +
  52 + //默认并发数
  53 + private final int defaultMaxPerRoute = 10;
  54 +
  55 + private CloseableHttpClient httpClient;
  56 +
  57 + @PostConstruct
  58 + public void init() {
  59 + new Thread(() -> {
  60 + while (Objects.isNull(httpClient)) {
  61 + try {
  62 + httpClient = this.buildHttpClient();
  63 + } catch (Exception e) {
  64 + log.warn("build http client fail {}", e.getMessage());
  65 + }
  66 + try {
  67 + Thread.sleep(3 * 1000);
  68 + } catch (InterruptedException e) {
  69 +
  70 + }
  71 + }
  72 + }, "http-client-builder").start();
  73 + }
  74 +
  75 + public CloseableHttpClient buildHttpClient() throws Exception {
  76 + HttpClientBuilder b = HttpClientBuilder.create();
  77 +
  78 + // setup a Trust Strategy that allows all certificates.
  79 + //
  80 + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null,
  81 + new TrustStrategy() {
  82 + @Override
  83 + public boolean isTrusted(X509Certificate[] arg0, String arg1)
  84 + throws CertificateException {
  85 + return true;
  86 + }
  87 + }).build();
  88 + b.setSSLContext(sslContext);
  89 +
  90 + // don't check Hostnames, either.
  91 + // -- use SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if
  92 + // you don't want to weaken
  93 + HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
  94 +
  95 + // here's the special part:
  96 + // -- need to create an SSL Socket Factory, to use our weakened
  97 + // "trust strategy";
  98 + // -- and create a Registry, to register it.
  99 + //
  100 + SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
  101 + sslContext, hostnameVerifier);
  102 + Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
  103 + .<ConnectionSocketFactory>create()
  104 + .register("http",
  105 + PlainConnectionSocketFactory.getSocketFactory())
  106 + .register("https", sslSocketFactory).build();
  107 +
  108 + // now, we create connection-manager using our Registry.
  109 + // -- allows multi-threaded use
  110 + PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(
  111 + socketFactoryRegistry);
  112 + connMgr.setMaxTotal(maxTotal);
  113 + connMgr.setDefaultMaxPerRoute(defaultMaxPerRoute);
  114 + b.setConnectionManager(connMgr);
  115 +
  116 + //request config
  117 + RequestConfig requestConfig = RequestConfig.custom()
  118 + .setConnectionRequestTimeout(connectionRequestTimeout)
  119 + .setConnectTimeout(connectionTimeout)
  120 + .setSocketTimeout(socketTimeout)
  121 + .build();
  122 + b.setDefaultRequestConfig(requestConfig);
  123 +
  124 + // finally, build the HttpClient;
  125 + // -- done!
  126 + return b.build();
  127 + }
  128 +
  129 + public void destroy() {
  130 + if (httpClient != null)
  131 + httpClient.getConnectionManager().shutdown();
  132 + }
  133 +
  134 + /**
  135 + * Get请求
  136 + *
  137 + * @param url
  138 + * @return
  139 + * @throws Exception
  140 + */
  141 + public String get(String url) throws Exception {
  142 + HttpGet httpget = new HttpGet(url);
122 return sendHttpRequest(httpget); 143 return sendHttpRequest(httpget);
123 - }  
124 -  
125 - /**  
126 - * Post请求  
127 - * @param url  
128 - * @param body  
129 - * @return  
130 - * @throws Exception  
131 - */  
132 - public String post(String url, String body) throws Exception {  
133 - HttpPost httpPost = new HttpPost(url);  
134 - httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");  
135 - httpPost.setEntity(new StringEntity(body, "UTF-8"));  
136 - return sendHttpRequest(httpPost);  
137 - }  
138 -  
139 - /**  
140 - * 提交form-data  
141 - * @param url  
142 - * @param formDataMap  
143 - * @return  
144 - * @throws Exception  
145 - */  
146 - public String postFormData(String url, Map<String, String> formDataMap) throws Exception {  
147 - HttpPost httpPost = new HttpPost(url);  
148 - //httpPost.addHeader("Content-Type", "multipart/form-data;charset=UTF-8");  
149 - List <NameValuePair> nvps = new ArrayList <NameValuePair>();  
150 - if(formDataMap != null) {  
151 - for(Map.Entry<String, String> data : formDataMap.entrySet()) {  
152 - nvps.add(new BasicNameValuePair(data.getKey(), data.getValue()));  
153 - }  
154 - }  
155 - httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));  
156 - return sendHttpRequest(httpPost);  
157 - }  
158 -  
159 - /**  
160 - * http发送请求  
161 - * @param httpRequest  
162 - * @return  
163 - * @throws Exception  
164 - */  
165 - private String sendHttpRequest(HttpUriRequest httpRequest) throws Exception {  
166 - CloseableHttpResponse response = null;  
167 - try {  
168 - response = httpClient.execute(httpRequest);  
169 - int statusCode = response.getStatusLine().getStatusCode();  
170 - if (statusCode != HttpStatus.SC_OK) {  
171 - logger.error("http response code: {}, request: {}", statusCode, httpRequest.getURI());  
172 - throw new RuntimeException("http response status: " + statusCode);  
173 - }  
174 -  
175 - return EntityUtils.toString(response.getEntity(), "UTF-8");  
176 - }  
177 - finally {  
178 - if (response != null) {  
179 - try {  
180 - response.close();  
181 - } catch (Exception e) {  
182 - logger.error("pay httpclient resp close failed: {}", e.getMessage());  
183 - }  
184 - }  
185 - if(httpRequest != null) {  
186 - try {  
187 - httpRequest.abort();  
188 - } catch (Exception e) {  
189 - logger.error("pay httpclient req abort failed: {}", e.getMessage());  
190 - }  
191 - }  
192 - }  
193 - } 144 + }
  145 +
  146 + /**
  147 + * Post请求
  148 + *
  149 + * @param url
  150 + * @param body
  151 + * @return
  152 + * @throws Exception
  153 + */
  154 + public String post(String url, String body) throws Exception {
  155 + HttpPost httpPost = new HttpPost(url);
  156 + httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
  157 + httpPost.setEntity(new StringEntity(body, "UTF-8"));
  158 + return sendHttpRequest(httpPost);
  159 + }
  160 +
  161 + /**
  162 + * 提交form-data
  163 + *
  164 + * @param url
  165 + * @param formDataMap
  166 + * @return
  167 + * @throws Exception
  168 + */
  169 + public String postFormData(String url, Map<String, String> formDataMap) throws Exception {
  170 + HttpPost httpPost = new HttpPost(url);
  171 + //httpPost.addHeader("Content-Type", "multipart/form-data;charset=UTF-8");
  172 + List<NameValuePair> nvps = new ArrayList<NameValuePair>();
  173 + if (formDataMap != null) {
  174 + for (Map.Entry<String, String> data : formDataMap.entrySet()) {
  175 + nvps.add(new BasicNameValuePair(data.getKey(), data.getValue()));
  176 + }
  177 + }
  178 + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
  179 + return sendHttpRequest(httpPost);
  180 + }
  181 +
  182 + /**
  183 + * http发送请求
  184 + *
  185 + * @param httpRequest
  186 + * @return
  187 + * @throws Exception
  188 + */
  189 + private String sendHttpRequest(HttpUriRequest httpRequest) throws Exception {
  190 + CloseableHttpResponse response = null;
  191 + try {
  192 + response = httpClient.execute(httpRequest);
  193 + int statusCode = response.getStatusLine().getStatusCode();
  194 + if (statusCode != HttpStatus.SC_OK) {
  195 + logger.error("http response code: {}, request: {}", statusCode, httpRequest.getURI());
  196 + throw new RuntimeException("http response status: " + statusCode);
  197 + }
  198 +
  199 + return EntityUtils.toString(response.getEntity(), "UTF-8");
  200 + } finally {
  201 + if (response != null) {
  202 + try {
  203 + response.close();
  204 + } catch (Exception e) {
  205 + logger.error("pay httpclient resp close failed: {}", e.getMessage());
  206 + }
  207 + }
  208 + if (httpRequest != null) {
  209 + try {
  210 + httpRequest.abort();
  211 + } catch (Exception e) {
  212 + logger.error("pay httpclient req abort failed: {}", e.getMessage());
  213 + }
  214 + }
  215 + }
  216 + }
194 217
195 } 218 }
@@ -9,6 +9,7 @@ import org.apache.http.conn.socket.ConnectionSocketFactory; @@ -9,6 +9,7 @@ import org.apache.http.conn.socket.ConnectionSocketFactory;
9 import org.apache.http.conn.socket.PlainConnectionSocketFactory; 9 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
10 import org.apache.http.conn.ssl.NoopHostnameVerifier; 10 import org.apache.http.conn.ssl.NoopHostnameVerifier;
11 import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 11 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
  12 +import org.apache.http.impl.client.CloseableHttpClient;
12 import org.apache.http.impl.client.HttpClientBuilder; 13 import org.apache.http.impl.client.HttpClientBuilder;
13 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 14 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
14 import org.apache.http.ssl.SSLContextBuilder; 15 import org.apache.http.ssl.SSLContextBuilder;
@@ -33,8 +34,7 @@ public abstract class HttpSslClientAbstract extends HttpClient { @@ -33,8 +34,7 @@ public abstract class HttpSslClientAbstract extends HttpClient {
33 34
34 35
35 @Override 36 @Override
36 - @PostConstruct  
37 - public void init() throws Exception { 37 + public CloseableHttpClient buildHttpClient() throws Exception {
38 HttpClientBuilder b = HttpClientBuilder.create(); 38 HttpClientBuilder b = HttpClientBuilder.create();
39 39
40 // setup a Trust Strategy that allows all certificates. 40 // setup a Trust Strategy that allows all certificates.
@@ -82,7 +82,7 @@ public abstract class HttpSslClientAbstract extends HttpClient { @@ -82,7 +82,7 @@ public abstract class HttpSslClientAbstract extends HttpClient {
82 82
83 // finally, buildSellerBo the HttpClient; 83 // finally, buildSellerBo the HttpClient;
84 // -- done! 84 // -- done!
85 - httpClient = b.build(); 85 + return b.build();
86 } 86 }
87 87
88 private void loadKeyMaterial(SSLContextBuilder sslContextBuilder) throws Exception { 88 private void loadKeyMaterial(SSLContextBuilder sslContextBuilder) throws Exception {