一、背景
事業開発は、多くの場合、HTTP / HTTPSに要求を送信することにより、下流のサービスに遭遇します。繰り返し作成し、車輪に論理的な書き込みのHttpClient、および性能、機能ムラたびに。ここでは、高性能、汎用ツールベルトのHttpクライアントの接続プールを共有します。
:再現し、労働の作者の成果を尊重してください、元のリンク明記してくださいhttps://www.cnblogs.com/waterystone/p/11551280.htmlを
第二に、特性
- ApacheのパフォーマンスベースのHTTPクライアントorg.apache.http.client.HttpClient。
- デフォルトの接続プール20、200の最大数は、システム変数= -Dadu.common.http.max.totalで指定することができます。
- 接続プールのデフォルトルーティングごとの接続の最大数は2であり、-Dadu.common.http.max.per.route = 10システム変数で指定することができます。
- タイムアウトはhttpOptionsセットにより、設定することができます。
- HttpOptionsによって設定され、再試行してください。
第三に、ソース
参考:https://github.com/waterystone/adu-test/blob/master/src/main/java/com/adu/utils/HttpClientUtil.java
パッケージcom.adu.utils。 輸入com.adu.Constants。 輸入com.adu.handler.HttpRequestRetryHandler。 輸入com.adu.model.HttpOptions。 輸入org.apache.http.HttpEntity。 輸入org.apache.http.NameValuePair; 輸入org.apache.http.client.config.RequestConfig; 輸入org.apache.http.client.entity.UrlEncodedFormEntity。 輸入org.apache.http.client.methods.CloseableHttpResponse。 輸入org.apache.http.client.methods.HttpGet; 輸入org.apache.http.client.methods.HttpPost; 輸入org.apache.http.client.methods.HttpRequestBase; 輸入org.apache.http.client.utils.URIBuilder。 輸入org.apache.http.client.utils.URLEncodedUtils。 輸入org.apache.http.config.Registry。 輸入org.apache.http.config.RegistryBuilder。 輸入org.apache.http.conn.socket.ConnectionSocketFactory; 輸入org.apache.http.conn.socket.PlainConnectionSocketFactory; 輸入org.apache.http.conn.ssl.NoopHostnameVerifier; 輸入org.apache.http.conn.ssl.SSLConnectionSocketFactory; 輸入org.apache.http.entity.StringEntity。 輸入org.apache.http.impl.client.CloseableHttpClient。 輸入org.apache.http.impl.client.HttpClients。 輸入org.apache.http.impl.conn.PoolingHttpClientConnectionManager。 輸入org.apache.http.message.BasicNameValuePair; 輸入org.apache.http.ssl.SSLContextBuilder。 輸入org.apache.http.ssl.TrustStrategy。 輸入org.apache.http.util.EntityUtils。 輸入org.slf4j.Logger。 輸入org.slf4j.LoggerFactory; インポートjavax.net.ssl.SSLContext; インポートjava.nio.charset.StandardCharsets; インポートjava.security.cert.CertificateException; はjava.security.cert.X509Certificateのインポート; java.util.ArrayListの輸入。 java.util.Listのインポート、 インポートjava.util.Map; インポートjava.util.Objects; インポートjava.util.stream.Collectors; / ** *のHttpクライアントの接続プールとツール。次の特性を有している * <OL> </ LI>; * <LI> {@link org.apache.http.client.HttpClient} Apacheベースの性能HTTPクライアント * <LI>デフォルトの接続プールの最大数20、システム変数で指定され= 200 -Dzzarch.common.http.max.totalでき; </ LI> * <LI>接続プールのデフォルトルーティングシステムが-Dzzarch.commonにより可変とすることができる、2当たりの最大接続数.http.max.per.route = 10を指定します。</ LI> * <李> * <LI>可重试、通过{@link HttpOptions}进行设置</ LI> * @authorのduyunjie * @date 2019年9月18日午後04時33分 * / publicクラスHttpClientUtil { プライベート静的最終ロガーロガー= LoggerFactory。 getLogger(HttpClientUtil.class)。 / ** * HttpClientを连接池 * / プライベート静的PoolingHttpClientConnectionManager CONNECTION_MANAGER = initPoolingHttpClientConnectionManager(); 公共の静的な文字列HTTPGET(文字列のURL){例外をスロー (URL、NULL、NULL、NULL)HTTPGETを返します。 } 公共の静的な文字列HTTPGET(文字列のURL、HttpOptions httpOptionsが){例外をスロー リターンHTTPGET(URL、NULL、NULL、httpOptions)。 } 公共の静的な文字列HTTPGET(文字列のURL、地図<?文字列、> paramsが){例外がスローされます (URLは、null、パラメータ、ヌル)HTTPGETを返します。 } 公共の静的な文字列HTTPGET(文字列のURL、地図<?文字列> paramsは、HttpOptions httpOptions){例外をスロー (URL、ヌル、paramsは、httpOptions)HTTPGETを返します。 } 公共の静的な文字列HTTPGETは(<?文字列>文字列のURLマップヘッダーマップ<?文字列>のparams){例外をスローする (ヌルURL、ヘッダ、paramsは、)HTTPGETを返します。 } / ** *发送HTTP GET请求 * * @paramのURL * @paramヘッダ请求头 * @paramのparams请求参数 そのような再試行の回数、タイムアウト時間として* @param httpOptions構成パラメータ、。 * @return @throws例外* * / パブリック静的な文字列HTTPGET(文字列のURL、地図<文字列、?>ヘッダ、地図<文字列、?>のparams、httpOptions httpOptionsザ・)スロー例外{ //ロード要求アドレスとパラメータ URIBuilderのUB =新しいURIBuilder() ; ub.setPath(URL); //リクエストパラメータを変換し 、リスト<NameValuePairsの> = convertParams2NVPSペア(のparams) IF {(pairs.isEmpty()!) ub.setParameters(ペア); } HTTPGET HTTPGET =新新HTTPGET(UB。 ())を構築; //設定要求ヘッダ IF(Objects.nonNull(ヘッダ)){ } ため(ののMap.Entry <文字列、?> PARAM:headers.entrySet()){ httpGet.addHeader(param.getKey()、String.valueOf(param.getValue()))。 } (HTTPGET、httpOptions)doHttpを返します。 } 公共の静的な文字列httpPost(文字列のURLは、地図<?文字列>のparams)は例外{スロー (ヌル、URL、ヌル、paramsは)httpPostを返します。 } 公共の静的な文字列httpPost(文字列のURL、地図<?文字列> paramsは、HttpOptions httpOptions){例外をスロー (URL、ヌル、paramsは、httpOptions)httpPostを返します。 } 公共の静的な文字列httpPostは(<?文字列>文字列のURLマップヘッダーマップ<?文字列>のparams){例外をスローする (ヌルURL、ヘッダ、paramsは、)httpPostを返します。 } / ** *发送HTTP POST请求 * * @paramのURL * @paramヘッダ请求头 * @paramのparams请求参数 などの再試行回数、タイムアウト時間として* @param httpOptions設定パラメータ、。 @return * * @throws例外 * / パブリック静的文字列HttpPost(<?文字列、>文字列のURL、地図ヘッダは、地図<?文字列>のparams、httpOptions httpOptionsザ・は){例外がスローされます HttpPost HttpPost =新新HttpPost(URL); //変換要求パラメータ リスト<NameValuePairsの> = convertParams2NVPS対(paramsは); もし{(!pairs.isEmpty()) httpPost.setEntity(新しい新しいUrlEncodedFormEntity(ペア、StandardCharsets.UTF_8.name())); } //要求ヘッダーを設定 する場合(Objects.nonNull(ヘッダ)){ 用の(のMap.Entry <?文字列> PARAM:headers.entrySet()){ httpPost.addHeader(param.getKey()、String.valueOf(param.getValue()))。 } } doHttpリターン(httpOptions HttpPost); } / ** *送信されたHTTP POSTリクエスト、フォーマットJSONで * <P>リクエストパラメータがJSONでありますフォーマット、データが符号化されている。8 UTF </ P> * * @paramのURL * @param用のparam *の@return *例外@throws * / パブリック静的文字列httpPostJson(URL文字列、文字列PARAM、httpOptions httpOptionsザ)は例外{スロー HttpPost HttpPost =をHttpPost新新(URL); //設定リクエストヘッダ httpPost.addHeader( "Content-Typeの"、 "ファイルアプリケーション/ JSON;のcharset = UTF-8"); //リクエストパラメータを設定します httpPost.setEntity(新しい新しいStringEntity(PARAM、StandardCharsets.UTF_8.name())); doHttp(HttpPost、httpOptions)を返す; } / ** *送信されたHTTP POSTリクエスト、フォーマットXMLで * <P>リクエストパラメータは、XML形式であります8データエンコーディングがUTFである</ P> * * @paramのURL * @param用のparam *の@return *例外@throws * / パブリック静的文字列httpPostXml(URL文字列、文字列PARAM、httpOptions httpOptionsザが){例外をスロー HttpPost HttpPost =新しい新しいHttpPost (URL); //設定リクエストヘッダ httpPost.addHeader( "コンテンツタイプ"、 "ファイルアプリケーション/ XML;のcharset = UTF-8"); //設定要求パラメータ httpPost.setEntity(新しい新しいStringEntity(PARAM、StandardCharsets.UTF_8.name())); doHttp(HttpPost、httpOptions)を返す; } / ** *変換要求パラメータ、キーと値のペアは、地図のQueryString列をステッチ * * paramsはを@param * @戻る * / パブリック静的文字列convertParams2QueryStr(MAP <文字列、?>のparams){ リスト<NameValuePairsの> = convertParams2NVPS対(paramsは); URLEncodedUtils.format(ペア、StandardCharsets.UTF_8.name())を返す; } / ** *変換をリクエストパラメータ * * @param paramsは * @return * / パブリック静的リスト<のNameValuePair> convertParams2NVPS(地図<文字列、?>のparams){ (paramsは== NULL){IF のArrayList <>(新しい新を返す); } params.entrySet()ストリーム()地図(PARAM返す- >新しい新しいBasicNameValuePair(param.getKey()、String.valueOf(param.getValueを(.. 。))))を収集(Collectors.toList()); } / ** //設定されたタイムアウト *发送HTTP请求 * * @param要求 * @return * @throws例外 * / プライベート静的な文字列doHttp(HttpRequestBase要求、HttpOptions httpOptions)例外{スロー IF(Objects.isNull(httpOptions)){//如果为空、则用の。默认的 httpOptions =新しいhttpOptions()。 } IF(Objects.nonNull(httpOptions.getTimeoutMs())){ request.setConfig(RequestConfig.custom()setSocketTimeout(httpOptions.getTimeoutMs())を作成()); } //设置重试策略 HttpRequestRetryHandler httpRequestRetryHandler = NULL; IF(Objects.nonNull(httpOptions.getRetryCount())){ httpRequestRetryHandler =新しいHttpRequestRetryHandlerを( httpOptions.getRetryCount()); } //接続プールによって取得されたオブジェクト ;.)CloseableHttpClientのHttpClient = HttpClients.custom()setConnectionManager(CONNECTION_MANAGER).setRetryHandler(httpRequestRetryHandler).build( doRequest(HttpClientを、Request)を返します; } / * * *処理HTTP / HTTPSリクエスト、リクエストの結果を返し * <P>注:デフォルト要求8エンコードUTF </ P> * * @paramのHttpClient * @param要求を @return * * @throws例外 * / プライベート静的doRequest文字列(のHttpClient CloseableHttpClient、HttpRequestBaseリクエスト)例外{スロー 文字列結果= NULLと、 CloseableHttpResponseレスポンス= NULL; 試み{ //リクエストの結果がGET 応答= httpClient.execute(要求); //解決要求が発生 HttpEntityエンティティresponse.getEntity =を(); //変換結果 結果= EntityUtils.toString(エンティティ、StandardCharsets.UTF_8.name()); //閉じるIOストリーム EntityUtils.consume(エンティティ); }最後に{ IF {(ヌル=レスポンス!) response.close(); } } リターン結果; } / ** *接続プールを初期化する * * @return * / 静的PoolingHttpClientConnectionManager initPoolingHttpClientConnectionManagerプライベート(){ // HTTP / HTTPS(すべての信頼できる証明書)を要求するために使用することができる接続プールを初期化 PoolingHttpClientConnectionManagerのConnectionManager =新しい新しいPoolingHttpClientConnectionManager(getRegistryの()); 接続プールの全体の接続//最大数 文字列maxTotal =はSystem.getProperty (Constants.SYSTEM_PROPERTY_KEY_HTTP_MAX_TOTAL); IF(Objects.nonNull(maxTotal)){ connectionManager.setMaxTotal(Integer.valueOf(maxTotal)); } //各経路の接続の最大数 文字列maxPerRoute =はSystem.getProperty(Constants.SYSTEM_PROPERTY_KEY_HTTP_MAX_PER_ROUTE)。 IF(Objects.nonNull(maxPerRoute)){ connectionManager.setDefaultMaxPerRoute(Integer.valueOf(maxPerRoute))。 } logger.info( "[ZZARCH_COMMON_SUCCESS_initPoolingHttpClientConnectionManager] maxTotal = {}、maxPerRoute = {}"、maxTotal、maxPerRoute)。 ConnectionManagerを返します。 } / ** *获取HTTPClientの注册器 * * @return *は例外@throws * / プライベート静的レジストリを<ConnectionSocketFactory> getRegistryの(){ {しようと RegistryBuilderを返します。<ConnectionSocketFactory>()を作成します。( "HTTP"(新PlainConnectionSocketFactoryを登録。))レジスタ( "HTTPS"、getSSLFactory())()を構築します。 }キャッチ(例外e){ logger.error( "[ERROR_getRegistry]"、E)。 } はnullを返します。 *取得HTTPS SSL接続ファクトリー * <P>証明書の検証をスキップし、すなわち、すべての証明書を信頼</ P> * * @return *は、例外を@throws * / プライベート静的SSLConnectionSocketFactory getSSLFactory()例外{スロー //設定HTTPS SSL証明書情報、証明書の検証がスキップされ、すなわち、すべての証明書要求HTTPS信頼 )SSLContextBuilder sslBuilder新しい新しいSSLContextBuilder =を(。loadTrustMaterial(ヌル、新しい新TrustStrategy(){ @Override ブールIsTrusted公開(X509Certificateの[]カテナalberghiera、認証タイプ文字列)CertificateExceptionスロー{ trueにリターン; } })。 // SSL証明書HTTPS接続コンテキストを取得 するSSLContext sslBuilder.buildのSSLContext =を(); // GET HTTPS接続ファクトリ SSLConnectionSocketFactory sslCsf =新しいSSLConnectionSocketFactory(SSLContextの、新しいString [] { "でSSLv2Hello"、 "のSSLv3"、 "TLSv1の"、 "TLSv1.2"}、ヌル、NoopHostnameVerifier.INSTANCE)。 sslCsfを返します。 } }
終わり