Ich habe kürzlich HTTPClient verwendet und das offizielle Dokument angesehen: HTTPClient -Implementierungen werden voraussichtlich threadssicher sein. Es wird empfohlen, dass die gleiche Instanz dieser Klasse für mehrere Anforderungsausführungen wiederverwendet wird. Die Übersetzung bedeutet: Die Implementierung von HTTPClient ist thread-sicher und kann dieselbe Instanz wiederverwenden, um mehrere Anforderungen auszuführen. Wenn wir auf diese Beschreibung stoßen, sollten wir denken, dass HTTPClient verkapselt werden muss. Da es verwendet wird, werden Federstiefel so kombiniert, HTTPClient zu verkapulieren.
1. Anfrage RETRY -Handler (Anfrage erneut der Verarbeitung)
Um den benutzerdefinierten Ausnahmemechanismus wirksam zu machen, muss die HTTPREQUESTRETRYRYLER -Schnittstelle implementiert werden. Der Code lautet wie folgt:
importieren java.io.ioException; importieren java.io.interruptedioxception; Importieren Sie java.net.unnownhostException; Importieren Sie javax.net.ssl.sSexception; importieren javax.net.ssl.slhandshakeException; import org.apache.http.httpenclosingRequest; import org.apache.http.httprequest; import org.apache.http.nohttpesponsexception; import org.apache.http.client.httprequestretryHandler; import org.apache.http.client.protocol.httpclientContext; import org.apache.http.conn.connectTimeoutexception; import org.apache.http.protocol.httpcontext; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; / *** Beschreibung: Httpclients Wiederholungsverarbeitungsmechanismus*/ @Configuration öffentliche Klasse myhttpRequestretryHandler {@Value ("$ {httpclient.config.retryTime}") // Hier wird empfohlen, @ConfigurationProperties zu verwenden (Prefix = "httpcl. @Bean public httpRequestretryHandler httprequestretryHandler () {// Anfrage RETRY Final int retryTime = this.retryTime; RETCORE NEU HTTPREQUESTRETRYHandler () {public boolean retryRequest (IOException -Ausnahme, int ExecutionCount, HttpContext -Kontext) {// NICHT wiederholen, wenn über die Anzahl der Wiederholung nach Return -Rety -Rety -Time -Rety -Return -Return -Return -Return -Return -Retury -Return -Return -Return -Return -Anzahl wird nicht mehr ausgefällt. } // Der Server unterscheidet die Verbindungsausnahme des Clients, wenn (Ausnahmeinstanz von NohttPesponsexception) {return true; } // Timeout Timeout Retyry if (Ausnahmeinstanz unterrupthioException) {return true; } // Unbekannter Host if (Ausnahmeinstanz unbekanntHostException) {return false; } // Verbindung abgelehnt, wenn (Ausnahmeinstanz von ConnectTimeOutException) {return false; } // SSL Handshake -Ausnahme if (Ausnahmeinstanz ssLexception) {return false; } HttpclientContext clientContext = httpclientContext.adapt (Kontext); Httprequest request = clientContext.getRequest (); if (! (Anfrageinstanz httpentityenclosingRequest)) {return true; } return false; }}; }} 2. Pooling Connection Manager (Verbindungspool -Management)
PoolinghttpclientConnectionManager wird zum Verwalten des Verbindungspools des Kunden verwendet und kann Dienste für Anforderungen von mehreren Threads bereitstellen. Der Code ist wie folgt:
import org.apache.http.config.registry; import org.apache.http.config.registryBuilder; import org.apache.http.conn.socket.Connectionsocketfactory; import org.apache.http.conn.socket.layeredConnectionSocketfactory; import org.apache.http.conn.socket.PlainConnectionsocketFactory; import org.apache.http.conn.ssl.sslconnectionsOcketfactory; import org.apache.http.impl.conn.poolinghttpclientConnectionManager; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; @Configuration öffentliche Klasse MypoolinghttpclientConnectionManager { / *** Maximale Anzahl von Verbindungen im Verbindungspool* / @Value ("$ {httpclient.config.connmaxtotal}") private Int connmaxtotal = 20; / ** * */ @value ("$ {httpclient.config.maxPerRoute}") private int maxperRoute = 20; / ** * Verbindungsüberlebenszeit, Einheit ist S */ @Value ("$ {httpclient.config.timetolive}") private int timetolive = 60; @Bean Public PoolinghttpclientConnectionManager PoolingClientConnectionManager () {PoolinghttpclientConnectionManager PoolhttpcconnMmanager = new PoolinghttpclientConnectionManager (60, TimeUnit.Seconds); // Maximale Anzahl von Verbindungen poolhttpcconnmanager.setmaxtotal (this.connmaxtotal); // Route Radix poolhttpcconnManager.setDefaultMaxperRoute (this.maxPerRoute); return poolhttpcconnmanager; }} HINWEIS: Wenn die HTTPClient -Instanz nicht mehr benötigt wird und nicht mehr in den Geltungsbereich liegt, ist es wichtig, seinen Verbindungsmanager zu schließen, um sicherzustellen, dass alle Verbindungen, die der Manager aktiv hält, geschlossen und die von diesen Verbindungen zugewiesenen Systemressourcen freigesetzt werden.
Der Konstruktor der obigen PoolinghttpclientConnectionManager -Klasse lautet wie folgt:
public poolinghttpclientConnectionManager (endgültiges langes Timetolive, endgültige Zeiteinheit) {this (getDefaultregistry (), Null, Null, Null, Timetolive, Tunit); } private statische Registrierung <ConbonctionsSocketFactory> getDefaultregistry () {return RegistryBuilder. <ConnectionsOcketFactory> create () .register ("http", PlainConnectionsOCKETFACTORTORY } Es gibt zwei maximale Verbindungen in der PoolinghttpclientConnectionManager -Konfiguration, die die maximale Verbindungsnummer der Gesamtverbindung und die maximale Verbindungsnummer pro Route steuern. Wenn es keine explizite Einstellung gibt, sind standardmäßig nur bis zu 2 Verbindungen pro Route zulässig, und die Gesamtzahl der Verbindungen überschreitet 20 nicht. Dieser Wert reicht für viele Anwendungen mit hoher Parallelität nicht aus. Der entsprechende Wert muss gemäß der tatsächlichen Situation festgelegt werden. Die Idee ähnelt der Größe des Fadenpools. Wenn alle Verbindungsanforderungen derselben URL erfolgen
Besonderer Hinweis: Wenn Sie eine Verbindung wiederverwenden möchten, müssen Sie die Systemressourcen erstellen, die sie ordnungsgemäß freigegeben haben. Die Release -Methode lautet wie folgt:
Wenn Sie OutputStream verwenden, müssen Sie sicherstellen, dass die gesamte Entität ausgeschrieben ist. Wenn es sich um einen InputStream handelt, müssen Sie daran denken, InputStream.close () am Ende aufzurufen. Oder verwenden Sie Entityutils.consume (Entity) oder Entityutils.consumequiet (Entität), um die Entität vollständig erschöpft zu machen (letztere wirft keine Ausnahmen), um dies zu tun. In EntityUtils gibt es eine ToString -Methode, die ebenfalls sehr bequem ist (der InputStream wird am Ende automatisch geschlossen, wenn diese Methode aufgerufen wird, aber im tatsächlichen Testprozess wird die Verbindung nicht freigegeben), kann jedoch nur verwendet werden, wenn festgestellt werden kann, dass die empfangene Entität nicht besonders groß ist. Wenn die gesamte Entität nicht vollständig konsumiert ist, kann die Verbindung nicht wiederverwendet werden, und bald werden die verfügbaren Verbindungszeitüberschreitungen oder Blöcke hier nicht im Verbindungspool erhalten (da der Zustand der Verbindung immer verschont bleibt, dh der verwendete Zustand). Wenn Sie die Verbindung wiederverwenden möchten, müssen Sie sich daher daran erinnern, die Entität vollständig zu konsumieren. Solange der EOF des Streams erkannt wird, wird die Veröffentlichungsmethode des Anbieters automatisch zur Verarbeitung gefordert.
3.. Verbindungsstrategie Keep Wearing Strategie
In der HTTP -Spezifikation wird nicht angegeben, wie lange eine anhaltende Verbindung am Leben bleibt und sollte. Einige HTTP-Server verwenden nicht standardmäßige Keep-Alive-Header, um die Clients in Sekunden Zeit mit den Clients zu kommunizieren, wenn sie beabsichtigen, die Verbindung auf der Serverseite zu halten. Httpclient kann diese Informationen verwenden. Wenn der Keep-Alive-Header in der Antwort nicht vorhanden ist, geht Httpclient davon aus, dass die Verbindung auf unbestimmte Zeit aktiv bleiben kann. Viele in der Regel verwendete HTTP -Server sind jedoch so konfiguriert, dass sie nach einem Zeitraum des inaktiven Status persistente Verbindungen löschen, um Systemressourcen zu sparen, ohne den Client zu benachrichtigen. Wenn die Standardrichtlinie zu optimistisch ist, müssen Sie möglicherweise eine benutzerdefinierte Keep-Alive-Richtlinie angeben, der Code lautet wie folgt:
import org.apache.http.headeErelement; import org.apache.http.headerElementiterator; import org.apache.http.httpresponse; import org.apache.http.conn.Connectionkeepalivestrategy; import org.apache.http.message.basicheaderElementiterator; import org.apache.http.protocol.http; import org.apache.http.protocol.httpcontext; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; / *** Beschreibung: Verbindungsunterhaltspolitik* @Author chhliu*/ @Configuration öffentliche Klasse MyConnectionKeepalivestrategy {@Value ("$ {httpclient.config.keepalivetime}") private int keepalivetime = 30; @Bean ("Connectionkeepalivestrategy") Public Connectionkeepalivestrategy Connectionkeepalivestrategy () {Neue Connectionkeepalivestrategy () {public long GetKeePaliveduration (httpresponse response, httpcontext context) response.Headeriterator (http.conn_keep_alive)); while (it.hasNext ()) {HeaderElement He = it.NextElement (); String param = he.getName (); String value = he.getValue (); if (value! } catch (numberFormatexception ignorieren) {}}} return 30 * 1000; }}; }} Hinweis: In allen Situationen, insbesondere heutzutage, werden nicht lange Verbindungen verwendet. Die meisten Systeme werden auf mehreren Servern bereitgestellt und haben Lastausgleichsfunktionen. Wenn wir beim Zugriff eine lange Verbindung führen, wirkt sich der Client nach dem Aussetzen dieses Servers auf den Client aus. Gleichzeitig können wir die Lastausgleichseigenschaften des Servers nicht vollständig verwenden. Stattdessen sind kurze Verbindungen vorteilhafter. Diese müssen nach bestimmten Bedürfnissen bestimmt werden, anstatt sie in einem Satz zusammenzufassen.
4. Httpclient Proxy -Konfiguration (Proxy -Konfiguration)
Der Code ist wie folgt, um den Proxy zu konfigurieren, wie folgt:
import org.apache.http.httphost; import org.apache.http.impl.conn.defaultProxyroutePlanner; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; / *** Beschreibung: httpclient proxy* @author chhliu*/ @configuration public class mydefaultProxyroutePlanner {// Die Host -Adresse des Proxys @Value ("$ {httpclient.config.proxyhost}") private String proxyHost; // Die Portnummer des Proxys @Value ("$ {httpclient.config.proxyport}") private int proxyport = 8080; @Bean public defaultProxyroutePlanner defaultProxyroutePlanner () {httphost proxy = new httphost (this.proxyhost, this.proxyport); Rückgabe neuer StandardProxyroutePlanner (Proxy); }} HTTPCLIENT unterstützt nicht nur einfache direkte Verbindungen, komplexe Routing -Richtlinien und Proxying. HTTPROUTEPLANNER basiert auf dem HTTP-Kontext, der Client-zu-Server-Routing-Computing-Richtlinie. Wenn es keinen Proxy gibt, müssen Sie dieses Ding nicht festlegen. Hier gibt es ein sehr kritisches Konzept - Route: In Httpclient bezieht sich eine Route auf eine Linie der laufenden Umgebung.
5. RequestConfig
Die verschiedenen Konfigurationen, die zur Festlegung der Anforderung verwendet werden, ist der Code wie folgt:
import org.apache.http.client.config.requestconfig; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; @Configuration Public Class MyRequestConfig {@Value ("$ {httpclient.config.connectTimeout}") private int ConnectTimeout = 2000; @Value ("$ {httpclient.config.connectrAwealTimeout}") Private intEmScorrequestTimeout = 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 ist eine Konfiguration der Anfrage. Es gibt drei Zeitlimiten, die wichtiger sind. Standardmäßig sind alle drei Zeitleiterzeiten 0 (wenn die Konfiguration der Anforderung nicht festgelegt ist, werden die Standardparameter in httpclientParamConfigs GetRequestConfig während der Ausführung festgelegt). Dies bedeutet, dass unendliches Warten leicht alle Anfragen dazu führen kann, an diesem Ort auf unbestimmte Zeit zu blockieren und zu warten. Diese drei Auszeiten sind:
A. ConnectionRequestTimeout - Timeout, um eine Verbindung aus dem Verbindungspool zu erhalten
Dieses Mal definiert die Zeitüberschreitung für das Abrufen der Verbindung aus dem von ConnectionManager verwalteten Verbindungspool. Wenn im Verbindungspool keine Verbindung verfügbar ist, wird die Anforderung blockiert und die maximale Zeit, um auf ConnectionRequestTimeout zu warten. Wenn es nicht serviert wurde, wird eine ConnectionPoolTimeoutException -Ausnahme ausgelöst und es ist kein weiteres Warten zulässig.
B. ConnectTimeout - Timeout -Zeit
Dieses Mal definiert die Zeitüberschreitung für die Herstellung einer Verbindung mit dem Server über das Netzwerk, dh die Verbindungswartzeit zur Verbindung zur Ziel -URL, nachdem eine Verbindung im Verbindungspool erhalten wurde. Eine Zeitüberschreitung tritt auf, eine Ausnahme von ConnectionTimeoutException wird ausgelöst.
C. SCOCKETTIMEOUT - Auszeitungszeit
Dieses Mal definiert die Zeitüberschreitungszeit für Socket -Lesedaten, dh die Zeit, die zum Warten nach der Verbindung zum Server benötigt wird, um Antwortdaten vom Server zu erhalten, oder die Zeit, die benötigt wird, um die Antwort nach der Verbindung mit der vorherigen URL zu erhalten. Eine Zeitüberschreitung tritt auf und eine SockettimeoutException -Ausnahme wird ausgelöst.
6. Instantiert httpclient
Der HTTPClient wird durch die Implementierung von FactoryBean instanziiert. Der Code lautet wie folgt:
import org.apache.http.client.httprequestretryHandler; import org.apache.http.client.config.requestconfig; import org.apache.http.impl.conn.Connectionkeepalivestrategy; import org.apache.http.impl.client.cloSeableHttpclient; import org.apache.http.impl.client.httpclients; import org.apache.http.impl.conn.defaultProxyroutePlanner; import org.apache.http.impl.conn.poolinghttpclientConnectionManager; import org.springframework.bean.factory.DisposableBean; import org.springframework.beans.factory.factoryBean; import org.springframework.bean.factory.initializingBean; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.service; / *** Beschreibung: Httpclient Client -Kapselung*/ @Service ("httpclientManagerFactoryBen") öffentliche Klasse httpclientManagerFactoryBen FactoryBean <CloseableHttpclient>, Initialisierungsbean, DispositableBean {/ *** Zielobjekt, das durch FactoryBean*/ private Clospeable -SPOTTPLISS -SPOTHTTPLIENT ERGEBNIST wurde. @Autowired Private Connectionkeepalivestrategy Connectionkeepalivestrategy; @Autowired Private httprequestretryHandler httprequestretryHandler; @Autowired Private DefaultProxyroutePlanner ProxyroutePlanner; @Autowired Private PoolinghttpclientConnectionManager PoolhttpcconnManager; @Autowired Private RequestConfig Config; // Wenn Sie den Kontext zerstören, löst die Zerstörung der httpclient @Override public void destroy () die Ausnahme aus. Da der von ihm verwendete Verbindungsmanager hier geschlossen ist. */ if (null! = this.client) {this.client.close (); }} @Override // Initialisieren Sie die Instanz public void AfterPertieStieSet () Ausläufe Ausnahme {/ * * Es wird empfohlen, httpclients zu verwenden. Httpclients ist in der Tat nachweislich. Das unveränderliche Objekt kann nicht nur sicherstellen, dass der Zustand des Objekts nicht geändert wird, sondern auch von anderen Threads geteilt werden kann, ohne den Sperrmechanismus zu verwenden. .setRoutePlanner (ProxyroutePlanner) .SetDefaultrEquestConfig (config) .build (); } // den Typ der Instanz @Override public CloSableableHttpClient getObject () ausreihen {return this.client; } @Override public class <?> GetObjecttype () {return (this.client == null? ConnableableaShttpclient.class: this.client.getClass ()); } // Die gebaute Instanz ist ein Singleton@Override public boolean issingleton () {return true; }}7. Konfigurationsdateien hinzufügen
# Proxy -Host httpclient.config.proxyhost = xxx.xx.xx.xx # Proxy -Port httpclient.config.proxyport = 8080 # Verbindung Timeout oder Ausnahme Wiederholungszeiten httpclient.config.rytime = 3 # Langzeitverbindung. Im Verbindungspool httpclient.config.connmaxtotal = 20 httpclient.config.maxPerRoute = 20 # Verbindungszeitlimit httpclient.config.connectrequesttimeout = 2000 # Sock Timeout httpclient.config.sockettimeout = 2000 # Verbindungsüberlebenszeit, Einheit S httpclient.config.timetolive = 60
8. Test
Der Testcode lautet wie folgt:
importieren java.io.ioException; import Java.util.concurrent.executorService; import Java.util.concurrent.executors; import Javax.annotation.Resource; import org.apache.http.consts; import org.apache.http.parseException; import org.apache.http.client.clientProtocolException; import org.apache.http.client.methods.closenableHttPesponse; import org.apache.http.client.methods.httpget; import org.apache.http.impl.client.cloSeableHttpclient; import 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 {// Inject httpclient Instance @resource (name = "httpclientManagerFactoryBen") privat CloseableHttpclient Client; @Test public void test () löst ClientProtocolException, IOException, InterruptedException aus {ExecutorService Service = Executors.NewFixedThreadpool (2); für (int i = 0; i <10; i ++) {service.submit (new Runnable () {@Override public void run () {System.out.println ("Der aktuelle Thread ist:"+thread.currentThread (). GetName (); Httpget ("https: // localhost: 8080/testjson"); System.out.println("======================================================================================; EntityUtils.consumeQuietly(entity);// Release the Verbindung} catchProtocolexception E) {E.PrintStackTrace (); }); In den obigen Schritten wird die Einkapselung von HTTPClient im Wesentlichen abgeschlossen. Wenn Sie detaillierter sein müssen, können Sie den HTTPClient als httpclientTemplate nach den oben genannten Ideen nach und nach verbessern, da CloseableHttpclient einen Rückrufmechanismus intern verwendet, der Jdbctemplate oder Redistemplate ähnlich ist, bis der Service in Form von Spring Boot -Startbetrieben bereitgestellt wird.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.