Was ist der Unterschied zwischen CloseableHttpClient und HttpClient in der Apache HttpClient-API?

83

Ich studiere eine von unserer Firma entwickelte Anwendung. Es verwendet die Apache HttpClient-Bibliothek. Im Quellcode werden mithilfe der HttpClientKlasse Instanzen erstellt, um eine Verbindung zu einem Server herzustellen.

Ich möchte mehr über Apache HttpClient erfahren und habe diese Beispiele durchgearbeitet . Alle Beispiele verwenden CloseableHttpClientanstelle von HttpClient. Also ich denke CloseableHttpClientist eine erweiterte Version von HttpClient. Wenn dies der Fall ist, habe ich zwei Fragen:

  • Was ist der Unterschied zwischen diesen beiden?
  • Welche Klasse wird für meine Neuentwicklung empfohlen?
Nayana Adassuriya
quelle
7
Die Dokumentation scheint mir ziemlich klar zu sein: "Basisimplementierung von HttpClient, die auch Closeable implementiert" - HttpClient ist eine Schnittstelle; CloseableHttpClient ist eine abstrakte Klasse. Da sie jedoch AutoCloseable implementiert, können Sie sie in einer Try-with-Resources-Anweisung verwenden.
Jon Skeet
3
@ JonSkeet Das ist klar, aber wie wichtig ist es, HttpClientInstanzen zu schließen ? Wenn es wichtig ist, warum ist die close()Methode nicht Teil der Basisschnittstelle?
Jules
3
@ Jules: Ich fürchte, ich weiß nicht genug über HttpClient, um darauf zu antworten :(
Jon Skeet
Schließen muss nicht Teil der Basisschnittstelle sein, da die zugrunde liegende Verbindung automatisch an den Verbindungsmanager zurückgegeben wird
Jeril Kuruvila,

Antworten:

97
  • Der Haupteinstiegspunkt der HttpClient-API ist die HttpClient-Schnittstelle.
  • Die wichtigste Funktion von HttpClient ist die Ausführung von HTTP-Methoden.
  • Die Ausführung einer HTTP-Methode umfasst einen oder mehrere HTTP-Anforderungs- / HTTP-Antwortaustausche, die normalerweise intern von HttpClient ausgeführt werden.

  • CloseableHttpClient ist eine abstrakte Klasse, die die Basisimplementierung von HttpClient darstellt und auch java.io.Closeable implementiert.
  • Hier ist ein Beispiel für den Anforderungsausführungsprozess in seiner einfachsten Form:

    CloseableHttpClient httpclient = HttpClients.createDefault ();
    HttpGet httpget = new HttpGet ("http: // localhost /");
    CloseableHttpResponse response = httpclient.execute (httpget);
    Versuchen {
        //etwas tun
    } endlich {
        response.close ();
    }}

  • Freigabe der HttpClient-Ressource: Wenn eine Instanz CloseableHttpClient nicht mehr benötigt wird und bald den Gültigkeitsbereich verlässt, muss der damit verbundene Verbindungsmanager durch Aufrufen der CloseableHttpClient # close () -Methode heruntergefahren werden.

    CloseableHttpClient httpclient = HttpClients.createDefault ();
    Versuchen {
        //etwas tun
    } endlich {
        httpclient.close ();
    }}

Weitere Informationen finden Sie in der Referenz .


@Scadge Seit Java 7 stellt die Verwendung der Anweisung try-with-resources sicher, dass jede Ressource am Ende der Anweisung geschlossen wird. Es kann sowohl für den Client als auch für jede Antwort verwendet werden

try(CloseableHttpClient httpclient = HttpClients.createDefault()){

    // e.g. do this many times
    try (CloseableHttpResponse response = httpclient.execute(httpget)) {
    //do something
    }

    //do something else with httpclient here
}
Sagar Pudi
quelle
57
Diese Antwort wirft die Frage auf. Was bewirkt das Aufrufen von close () auf einem HttpClient, was sonst nicht passieren würde? Lecken Sie Verbindungen, wenn Sie close () nicht zu den entsprechenden Zeiten / Orten aufrufen? Beeinträchtigt das vorzeitige Aufrufen von close () Ihre Leistung, indem Sie die Verbindung wiederherstellen, wenn Sie dies wirklich nicht mussten?
Gilbertpilz
4
Ich habe den Code in httpclient nach der Antwort auf diese Frage durchsucht. Die Antwort ist, dass die Methode close verwendet wird, um den internen Status zu schließen. Einige der Implementierungen von HTTPClient (in der httpclient-Bibliothek) können so konfiguriert werden, dass persistente Ressourcen wie PooledHttpClientConnectionManager für Poolverbindungen verwendet werden. Ohne eine solche Methode könnten Sie diese Ressourcen bei Bedarf nicht bereinigen.
Deadron
@SugarPudi in dem obigen Beispiel, wir schließen müssen httpgetauch
Kasun Siyambalapitiya
Wie können wir hier Methoden für die abstrakte Klasse (CloseableHttpClient) aufrufen? Sollten wir nicht zuerst eine konkrete Unterklasse erstellen?
Illcar
@illcar Bitte gehen Sie durch diese Antwort, um das Konzept stackoverflow.com/a/4321402/2830834
Sagar Pudi
26

Hatte die gleiche Frage. Die anderen Antworten scheinen nicht zu sagen, warum close () wirklich notwendig ist. Außerdem schien Op Schwierigkeiten zu haben, die bevorzugte Art der Arbeit mit HttpClient et al.


Laut Apache :

// The underlying HTTP connection is still held by the response object
// to allow the response content to be streamed directly from the network socket.
// In order to ensure correct deallocation of system resources
// the user MUST call CloseableHttpResponse#close() from a finally clause.

Darüber hinaus lauten die Beziehungen wie folgt:

HttpClient (Schnittstelle)

implementiert von:

CloseableHttpClient - ThreadSafe.

DefaultHttpClient- ThreadSafe ABER veraltet , verwenden Sie HttpClientBuilderstattdessen.

HttpClientBuilder- NICHT ThreadSafe, ABER erstellt ThreadSafe CloseableHttpClient.

  • Verwenden Sie diese Option, um CUSTOM zu erstellen CloseableHttpClient.

HttpClients- NICHT ThreadSafe, ABER erstellt ThreadSafe CloseableHttpClient.

  • Verwenden Sie diese Option, um DEFAULT oder MINIMAL zu erstellen CloseableHttpClient.

Der bevorzugte Weg nach Apache:

CloseableHttpClient httpclient = HttpClients.createDefault();

Das Beispiel, das sie geben, ist httpclient.close()in der finallyKlausel enthalten und wird auch verwendet ResponseHandler.


Als Alternative ist die Art und Weise, wie Mkyong es macht, auch ein bisschen interessant:

HttpClient client = HttpClientBuilder.create().build();

Er zeigt keinen client.close()Anruf, aber ich würde denken, dass es notwendig ist, da clientes immer noch eine Instanz von ist CloseableHttpClient.

Euphorie99
quelle
15

Die anderen Antworten scheinen nicht zu sagen, warum close()das wirklich notwendig ist. * 2

Zweifel an der Antwort "HttpClient-Ressourcenfreigabe".

Es wird im alten 3.x httpcomponents- Dokument erwähnt , das lange zurückliegt und einen großen Unterschied zu 4.x HC aufweist. Außerdem ist die Erklärung so kurz, dass sie nicht sagt, was diese zugrunde liegende Ressource ist.

Ich habe einige Nachforschungen über den Quellcode von 4.5.2 angestellt und festgestellt, dass die Implementierung von im CloseableHttpClient:close()Grunde nur den Verbindungsmanager schließt.

(Zu Ihrer Information) Wenn Sie einen gemeinsam genutzten PoolingClientConnectionManagerClient und einen Anrufclient verwenden close(), tritt daher eine Ausnahme java.lang.IllegalStateException: Connection pool shut downauf. Um zu vermeiden, setConnectionManagerSharedfunktioniert.

Ich mache es lieber nichtCloseableHttpClient:close() nach jeder einzelnen Anfrage

Ich habe bei der Anforderung eine neue http-Client-Instanz erstellt und diese schließlich geschlossen. In diesem Fall ist es besser, nicht anzurufen close(). Wenn der Verbindungsmanager kein "freigegebenes" Flag hat, wird er heruntergefahren, was für eine einzelne Anforderung zu teuer ist.

Tatsächlich habe ich auch in der Bibliothek gefunden, dass clj-http , ein Clojure-Wrapper über Apache HC 4.5, überhaupt nicht aufruft close(). Siehe func requestin der Datei core.clj

eval
quelle
1
Können Sie erklären, warum es besser ist, als setConnectionManagerShared zu verwenden und nach jeder Anfrage close () aufzurufen?
Zyfo2
9

In der nächsten Hauptversion wird die Bibliotheksschnittstelle HttpClienterweitert Closeable. Bis dahin wird die Verwendung empfohlen, CloseableHttpClientwenn keine Kompatibilität mit früheren 4.x-Versionen (4.0, 4.1 und 4.2) erforderlich ist.

ok2c
quelle
8

HttpClientist keine Klasse, es ist eine Schnittstelle. Sie können es nicht so für die Entwicklung verwenden, wie Sie es meinen.

Was Sie wollen, ist eine Klasse, die die HttpClientSchnittstelle implementiert , und das ist CloseableHttpClient.

M. Sfakianos
quelle
2

CloseableHttpClientist die Basisklasse der httpclient-Bibliothek, die von allen Implementierungen verwendet wird. Andere Unterklassen sind größtenteils veraltet.

Das HttpClientist eine Schnittstelle für diese Klasse und andere Klassen.

Sie sollten dann das CloseableHttpClientin Ihrem Code verwenden und es mit dem erstellen HttpClientBuilder. Wenn Sie den Client umbrechen müssen, um ein bestimmtes Verhalten hinzuzufügen, sollten Sie Anforderungs- und Antwortabfangjäger verwenden, anstatt mit dem umzubrechen HttpClient.

Diese Antwort wurde im Kontext von httpclient-4.3 gegeben.

polve
quelle
0

Jon Skeet sagte:

Die Dokumentation scheint mir ziemlich klar zu sein: "Basisimplementierung von HttpClient, die auch Closeable implementiert" - HttpClient ist eine Schnittstelle; CloseableHttpClient ist eine abstrakte Klasse. Da sie jedoch AutoCloseable implementiert, können Sie sie in einer Try-with-Resources-Anweisung verwenden.

Aber dann fragte Jules:

@ JonSkeet Das ist klar, aber wie wichtig ist es, HttpClient-Instanzen zu schließen? Wenn es wichtig ist, warum ist die Methode close () nicht Teil der Basisschnittstelle?

Antwort für Jules

close muss nicht Teil der Basisschnittstelle sein, da die zugrunde liegende Verbindung nach jeder Ausführung automatisch an den Verbindungsmanager zurückgegeben wird

Um die Try-with-Resources-Anweisung zu berücksichtigen. Es ist obligatorisch, Closeable zu implementieren. Daher in CloseableHttpClient enthalten .

Hinweis:

Die Methode close in AbstractHttpClient, die CloseableHttpClient erweitert, ist veraltet. Ich konnte den Quellcode dafür nicht finden.

Jeril Kuruvila
quelle
Dies scheint immer noch nicht zu antworten: "Wie wichtig ist es, HttpClient-Instanzen zu schließen?"
Vivek Chavda