私は最近、httpclientを使用し、公式の文書を見ました。httpclientの実装は、安全であると予想されます。このクラスの同じインスタンスが複数のリクエスト実行のために再利用されることをお勧めします。翻訳は、HTTPCLIENTの実装はスレッドセーフであり、同じインスタンスを再利用して複数のリクエストを実行することができます。この説明に遭遇したとき、httpclientをカプセル化する必要があると考えるべきです。 Spring Bootを使用するため、Spring Bootを組み合わせてHttpClientをカプセル化します。
1.再試行ハンドラーをリクエストします(再試行処理をリクエスト)
カスタム例外メカニズムを有効にするために、httprequestretryhandlerインターフェイスを実装する必要があります。コードは次のとおりです。
java.io.ioexceptionをインポートします。 java.io.interruptedioexceptionをインポートします。 java.net.unknownhostexceptionをインポートします。 javax.net.ssl.sslexceptionをインポートします。 javax.net.ssl.sslhandshakeexceptionをインポートします。 org.apache.http.httpenclosingRequestをインポートします。 org.apache.http.httprequestをインポートします。 org.apache.http.nohttpresponseexceptionをインポートします。 org.apache.http.client.httprequestretryhandlerをインポートします。 import org.apache.http.client.protocol.httpclientContext; Import org.apache.http.conn.connecttimeoutexception; org.apache.http.protocol.httpcontextをインポートします。 Import org.springframework.beans.factory.annotation.value; org.springframework.context.annotation.beanをインポートします。 org.springframework.context.annotation.configurationをインポートします。 / ***説明:httpclientの再試行処理メカニズム*/ @configuration public class myhttprequestretryhandler {@value( "$ {httpclient.config.retrytime}")//ここで@bean public httprequestretryhandler httprequestretryhandler(){// request requestry final int retrytime = this.retrytime; new httprequestretryhandler(){public boolean retryrequest(ioexception Exception、int executionCount、httpContextコンテキスト){// retryの数が再試行時間を超えた場合、最大再試行カウントを超えても再試行しない場合、リクエストはexecutioncount> = retrytime> = retrytime) } //サーバーは、クライアントの接続例外を破壊します(例外Instance of nohttpresponsexception){return true; } //タイムアウトタイムアウトRetry if(Intecution intanceof interruptedioexception){return true; } //不明なホストif(exception instance of nowndhostexception){return false; } //接続が拒否された場合(connecttimeoutexceptionの例外Instance){return false; } // SSLハンドシェイク例外if(sslexceptionの例外インスタンス){return false; } httpclientContext clientContext = httpclientContext.Adapt(context); httprequest request = clientContext.getRequest(); if(!(httpentityenclosingRequest))){return true; } falseを返します。 }}; }} 2。接続マネージャーのプーリング(接続プール管理)
PoolingHttpClientConnectionManagerは、クライアントの接続プールを管理するために使用され、複数のスレッドからのリクエストのサービスを提供できます。コードは次のとおりです。
Import org.apache.http.config.registry; org.apache.http.config.registrybuilderをインポートします。 org.apache.http.conn.socket.connectionSocketFactoryをインポートします。 org.apache.http.conn.socket.layeredConnectionSocketFactoryをインポートします。 org.apache.http.conn.socket.plainconnectionsocketfactoryをインポートします。 org.apache.http.conn.ssl.sslconnectionSocketFactoryをインポートします。 import org.apache.http.impl.conn.poolinghttpclientConnectionManager; Import org.springframework.beans.factory.annotation.value; org.springframework.context.annotation.beanをインポートします。 org.springframework.context.annotation.configurationをインポートします。 @configuration public class mypoolinghttpclientconnectionmanager { / ***接続プールの接続の最大数* / @value( "$ {httpclient.config.connmaxtotal}")private int connmaxtotal = 20; / ** * */ @value( "$ {httpclient.config.maxperroute}")private int maxperroute = 20; / ** *接続サバイバル時間、ユニットはs */ @value( "$ {httpclient.config.timeTolive}")private int timetolive = 60; @bean public poolinghttpclientConnectionManager poolingClientConnectionManager(){poolinghttpclientConnectionManager poolehttpcconnmanager = new poopleinghttpclientConnectionManager(60、TimeUnit.seconds); //接続の最大数poolhttpcconnmanager.setmaxtotal(this.connmaxtotal); //ルートRADIX POULHTTPCCONNMANAGER.SETDEFAULTMAXPERROUTE(this.maxperroute); poolhttpcconnmanagerを返します。 }}注:HTTPCLIENTインスタンスが不要になり、範囲外になっている場合、マネージャーがアクティブに保つすべての接続が閉じられ、それらの接続によって割り当てられたシステムリソースを解放するために、接続マネージャーを閉鎖することが重要です。
上記のPoolingHttpClientConnectionManagerクラスのコンストラクターは次のとおりです。
public PoolinghttpclientConnectionManager(最終的な長いタイムトリブ、最終TimeUnit Tunit){this(getDefaultregistry()、null、null、null、timetolive、Tunit); } private static registry <ConnectionSocketFactory> getDefaultregistry(){Return RegistryBuilder。<ConnectionSocketFactory> create().register( "http"、plainConnectionSocketAftory.getSocketFactory()).Register( "HTTPS"、SSLConnectionSocketory.getFactory.getSocketfactory() } PoolingHTTPCLIENTConnectionManager構成には2つの最大接続があり、それぞれルートあたりの合計接続数と最大接続数を制御します。明示的な設定がない場合、デフォルトでは、ルートごとに最大2つの接続のみが許可されており、接続の総数は20を超えません。この値は、高い並行性を持つ多くのアプリケーションでは十分ではありません。実際の状況に従って適切な値を設定する必要があります。アイデアは、スレッドプールのサイズに似ています。すべての接続要求が同じURLにある場合、maxperrouteの値をMaxtotalと一致させるように設定できるため、接続をより効率的に再利用できます
特別なメモ:接続を再利用する場合は、それが占有するシステムリソースを正しくリリースする必要があります。リリース方法は次のとおりです。
OutputStreamを使用している場合は、エンティティ全体が書き出されることを確認する必要があります。 InputStreamの場合は、最終的にinputstream.close()を呼び出すことを忘れないでください。または、entityutils.consume(entity)またはentityutils.consumequetly(エンティティ)を使用して、エンティティを完全に使い果たします(後者は例外を投げません)これを行う。 EntityUtilsにはToStringメソッドがありますが、これも非常に便利です(このメソッドを呼び出すと、入力ストリームは最終的に自動的に閉じられますが、実際のテストプロセスでは、接続はリリースされません)が、受信エンティティが特に大きくないと判断できる場合にのみ使用できます。エンティティ全体が完全に消費されていない場合、接続を再利用できず、すぐにここで利用可能な接続タイムアウトまたはブロックは接続プールで取得されません(接続の状態は常に免れ、つまり、使用されている状態)。したがって、接続を再利用する場合は、エンティティを完全に消費することを忘れないでください。ストリームのEOFが検出される限り、接続ホルダーのリリース接続法は自動的に処理のために呼び出されます。
3。接続を維持してください
HTTP仕様では、永続的な接続が生き続ける可能性がある期間は指定されていません。一部のHTTPサーバーは、非標準のキープアライブヘッダーを使用して、サーバー側の接続を維持する予定の数秒で期間をクライアントに通信します。 httpclientはこの情報を使用できます。 Keep-Aliveヘッダーが応答に存在しない場合、HTTPCLIENTは、接続が無期限にアクティブなままでいることを想定しています。ただし、一般的に使用される多くのHTTPサーバーは、クライアントに通知せずにシステムリソースを保存するために、非アクティブなステータスの後に永続的な接続を削除するように構成されています。デフォルトのポリシーが楽観的すぎる場合は、カスタムキープアライブポリシーを提供する必要がある場合があります。コードは次のとおりです。
org.apache.http.headerelementをインポートします。 org.apache.http.headerelementiteratorをインポートします。 org.apache.http.httpresponseをインポートします。 Import org.apache.http.conn.connectionkeepalivestrategy; org.apache.http.message.basicheaderementiteratorをインポートします。 org.apache.http.protocol.httpをインポートします。 org.apache.http.protocol.httpcontextをインポートします。 Import org.springframework.beans.factory.annotation.value; org.springframework.context.annotation.beanをインポートします。 org.springframework.context.annotation.configurationをインポートします。 / ***説明:接続キーピングポリシー* @Author chhliu*/ @configuration public class myconnectionkeepalivestrategy {@value( "$ {httpclient.config.keepalivetime}")private int keepalivetime = 30; @bean( "ConnectionKeepalivestrategy")public connectionkeepaliveStrategy connectionkeepalivestrategy(){return connectionkeepaliveStrestrestrategy(){public long getKeeparinversuration(httpcontext context){// henor 'keep-lerelemeneterator it = basichedereleterator it = basichedereleterator Response.Headeritorator(http.conn_keep_alive)); while(it.hasnext()){headerelement he = it.nextelement();文字列param = he.getname();文字列値= he.getValue(); if(value!= null && param.equalsignorecase( "timeout")){try {return long.parselong(value) * 1000; } catch(numberformatexception Ingrore){}}} return 30 * 1000; }}; }}注:長い接続はすべての状況では使用されていません。特に最近では、ほとんどのシステムは複数のサーバーに展開されており、ロードバランス機能を備えています。アクセス時に長い接続を維持すると、そのサーバーが中断されると、クライアントに影響します。同時に、サーバーの負荷分散特性を完全に利用することはできません。代わりに、短い接続がより有益です。これらは、特定のニーズに従って、1つの文でそれらを要約するのではなく、決定する必要があります。
4。HTTPCLIENTプロキシ構成(プロキシ構成)
プロキシの構成に使用すると、コードは次のとおりです。
org.apache.http.httphostをインポートします。 org.apache.http.impl.conn.defaultproxyrouteplannerをインポートします。 Import org.springframework.beans.factory.annotation.value; org.springframework.context.annotation.beanをインポートします。 org.springframework.context.annotation.configurationをインポートします。 / ***説明:httpclient proxy* @author chhliu*/ @configuration public class mydefaultproxyrouteplanner {// proxyのホストアドレス@value( "$ {httpclient.config.proxyhost}")private string proxyhost; // proxyのポート番号@value( "$ {httpclient.config.proxyport}")private int proxyport = 8080; @bean public defaultProxyrouteplanner defaultProxyrouteplanner(){httphost proxy = new httphost(this.proxyhost、this.proxyport);新しいDefaultProxyroutePlanner(プロキシ)を返します。 }} HTTPCLIENTは、単純な直接接続、複雑なルーティングポリシー、プロキシをサポートするだけではありません。 HTTPRoutePlannerは、クライアントからサーバーへのルーティングコンピューティングポリシーであるHTTPコンテキストに基づいています。一般的に、プロキシがない場合は、このことを設定する必要はありません。ここには非常に重要な概念があります - ルート:httpclientでは、ルートは実行環境マシンのラインを指します - >ターゲットマシンホスト、つまりターゲットURLのホストが同じ場合、ルートは同じです。
5。RequestConfig
リクエストの設定に使用されるさまざまな構成、コードは次のとおりです。
org.apache.http.client.config.RequestConfigをインポートします。 Import org.springframework.beans.factory.annotation.value; org.springframework.context.annotation.beanをインポートします。 org.springframework.context.annotation.configurationをインポートします。 @configuration public class myRequestConfig {@value( "$ {httpclient.config.connecttimeout}")private int connecttimeout = 2000; @value( "$ {httpclient.config.connectrequesttimeout}")private connectRequestTimeout = 2000; @value( "$ {httpclient.config.sockettimeout}")private int sockettimeout = 2000; @bean public requestconfig config(){return requestconfig.custom().setConnectionRequestTimeout(this.connectRequestTimeout).setConnectTimeout(this.ConnectTimeout).SetSockettimeout(this.sockettimeout).build(); }} RequestConfigは、リクエストの構成です。より重要な3つのタイムアウト時間があります。デフォルトでは、3つのタイムアウト時間はすべて0です(リクエストの構成が設定されていない場合、デフォルトのパラメーターは、実行中にhttpclientparamconfigのgetRequestConfigで設定されます)。これは、この場所ですべてのリクエストが無期限にブロックされ、待機することができる無限の待機を意味します。これらの3つのタイムアウトは次のとおりです。
a。 ConnectionRequestTimeOut—接続プールから接続を取得するためのTimeout
今回は、ConnectionManagerが管理する接続プールから接続を取得するためのタイムアウト時間を定義します。接続プールに利用可能な接続がない場合、リクエストはブロックされ、ConnectionRequestTimeOutを待つ最大時間がブロックされます。それが提供されていない場合、ConnectionPoolTimeOutException例外がスローされ、それ以上の待機は許可されません。
b。 ConnectTimeOut—接続タイムアウト時間
今回は、ネットワークを介してサーバーとの接続を確立するためのタイムアウト、つまり、接続プールで接続を取得した後にターゲットURLに接続するための接続待機時間を定義します。タイムアウトが発生し、ConnectionTimeTimeOutExceptionの例外がスローされます。
c。 SockettimeOut—リクエストタイムアウト時間
今回は、ソケット読み取りデータのタイムアウト時間、つまりサーバーに接続してサーバーから応答データを取得するのにかかる時間、または以前のURLに接続した後の応答を取得するのにかかる時間を定義します。タイムアウトが発生し、SockettimeOutExceptionの例外がスローされます。
6。HTTPCLIENTをインスタンス化します
HTTPCLIENTはFactoryBeanを実装することでインスタンス化されます。コードは次のとおりです。
org.apache.http.client.httprequestretryhandlerをインポートします。 org.apache.http.client.config.RequestConfigをインポートします。 org.apache.http.impl.conn.connectionkeepalivestrategyをインポートします。 import org.apache.http.impl.client.closablehttpclient; org.apache.http.impl.client.httpclientsをインポートします。 org.apache.http.impl.conn.defaultproxyrouteplannerをインポートします。 import org.apache.http.impl.conn.poolinghttpclientConnectionManager; Import org.springframework.beans.factory.disposablebean; Import org.springframework.beans.factory.factorybean; Import org.springframework.beans.factory.initializingbean; Import org.springframework.beans.factory.annotation.autowired; org.springframework.stereotype.serviceをインポートします。 / ***説明:httpClientクライアントカプセル化*/ @service( "httpclientmanagerfactoryben")パブリッククラスhttpclientmanagerfactorybenは、工場<coloseablehttpclient>、初期化bean、dapureablebean {/ ***ターゲットオブジェクトをFactorybean*/ privatebean*/ privatebean*/ privatebean*/ privatebean*/ privatebean*/ privebean*/ *** @autowired private connectionkeepalivestrategy connectionkeepalivestrategy; @autowired private httprequestretryhandler httprequestretryhandler; @autowired private defaultproxyrouteplanner proxyrouteplanner; @AutowiredプライベートPoolinghttpclientConnectionManager poolhttpcconnmanager; @autowired private requestconfig config; //コンテキストを破壊するとき、httpclientインスタンス@Override public void Destroy()を破壊する場合、例外{ / * * httpclient.close()を呼び出します。最初に接続マネージャーをシャットダウンし、次にhttpclientが占有しているすべてのリソースをリリースします。使用する接続マネージャーはここで閉じられているため *したがって、次回HTTPリクエストを行う必要がある場合、接続マネージャーを更新してHTTPClientを構築する必要があります。 */ if(null!= this.client){this.client.close(); }} @override //インスタンスの初期化public void abutpropertiesset()を初期化する例外{/ * * httpclients.customを使用してhttpclientbuilder.create()httpclientbuilder * htpclbuldedからhttpclientbuilder * htpclbuilder * from htpclbuilder *を作成する代わりに、ここでhttpclientbuilderを作成することをお勧めします。非読み取りセーフですが、httpclientsは確かにimutableです。不変のオブジェクトは、オブジェクトの状態が変更されないことを保証するだけでなく、ロックメカニズムを使用せずに他のスレッドで共有できます。 .setRoutePlanner(proxyrouteplanner).setDefaultrequestConfig(config).build(); } // instance @override public closeablehttpclient getobject()throws exception {return this.client; } @Override public class <? } //ビルドインスタンスはsingleton@override public boolean issingleton()です{return true; }}7.構成ファイルを追加します
#プロキシのホストhttpclient.config.proxyhost = xxx.xx.xx.xx.xx.xx.xx.xx.config.proxyport = 8080#接続タイムアウトまたはrectry retry times httpclient.config.retrytime = 3#長い接続時間、ユニットはhttpclientのマイキップインタームであり、接続プールの接続httpclient.config.connmaxtotal = 20 httpclient.config.maxperroute = 20#接続タイムアウト、ユニットms httpclient.config.connectimeout = 20#接続タイムアウト、ユニットはMS httpclient.config. httpclient.config.connectrequesttimeout = 2000#ソックタイムアウトhttpclient.config.sockettimeout = 2000#接続サバイバル時間、unit s httpclient.config.timetolive = 60
8。テスト
テストコードは次のとおりです。
java.io.ioexceptionをインポートします。 java.util.concurrent.executorserviceをインポートします。 java.util.concurrent.executorsをインポートします。 javax.annotation.resourceをインポートします。 org.apache.http.constsをインポートします。 org.apache.http.parseexceptionをインポートします。 org.apache.http.client.clientprotocolexceptionをインポートします。 org.apache.http.client.methods.closeablehttppresponseをインポートします。 org.apache.http.client.methods.httpgetをインポートします。 import org.apache.http.impl.client.closablehttpclient; org.apache.http.util.entityutilsをインポートします。 Import org.junit.test; Import org.junit.runner.runwith; import org.springframework.boot.test.context.springboottest; Import org.springframework.test.context.junit4.springrunner; @runwith(springrunner.class)@springboottest public class httpclientmanagerfactorybentest {// httpclient instance @resource(name = "httpclientmanagerfactoryben")private closeablehttpclientクライアント; @test public void test()throws clientProtocolexception、ioException、arturnedexception {executorservice service = executors.newfixedthreadpool(2); (int i = 0; i <10; i ++){servers.submit(new runnable(){@Overridide public void run(){system.out.out.println( "currentresd is is is:"+thread.currentthread()。getNamame()。getName()。getName(); getName(); getName(); getName(); getName(); httpentity entity = null try {httpget get = ne ne ne ne ne new httpget( "https:// localhost:8080/testjson"); System.out.println( "====================================================================================接続} CATCH(e.printStacktrace()} catch() })} sleep(60000)}上記の手順を通じて、HttpClientのカプセル化が基本的に完了します。より詳細にする必要がある場合は、上記のアイデアに従ってhttpClientTemplateとしてhttpClientを徐々に改善できます。これは、CloseableHttpClientが内部でコールバックメカニズムを使用します。これは、Spring Boot Starterの形でサービスを提供できるようになるまでJDBCtemplateまたはRediStemplateに似ています。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。