Java HttpClient obsolète - À quel point cela peut-il être difficile?

172

Tout ce que j'essaie de faire est de télécharger du JSON et de le désérialiser en objet. Je n'ai pas encore téléchargé le JSON.

Presque tous les exemples HttpClient que je peux trouver, y compris ceux du site Apache, ressemblent à quelque chose comme ...

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;

public void blah() {
    HttpClient client = new DefaultHttpClient();
    ...
}

Cependant, Netbeans me dit que DefaultHttpClientc'est obsolète. J'ai essayé de rechercher sur Google DefaultHttpClient deprecatedet autant d'autres variantes que je peux penser et je ne trouve aucun résultat utile, donc il me manque évidemment quelque chose.

Quelle est la méthode Java7 correcte pour télécharger le contenu d'une page Web? N'y a-t-il pas vraiment de client Http décent dans le langage? Je trouve cela difficile à croire.

Ma dépendance Maven pour cela est ...

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>LATEST</version>
    <type>jar</type>
</dependency>
De base
la source
2
NetBeans vous dit mal ou vous interprétez mal quelque chose. DefaultHttpClientn'est certainement pas obsolète. Quelle version avez-vous spécifiée dans votre POM?
Perception du
8
en 4.3-alpha1, il semble être obsolète
Arun P Johny
3
Vous avez raison, l'API httpclient est un trainwreck
Hans Westerbeek
2
Je vous recommande de définir la version sur un numéro de version majeur au lieu de LATEST. Cela vous permettra de contrôler manuellement le processus de mise à niveau et de ne pas laisser Maven décider à votre place.
Christophe Roussy
1
@Basic il peut changer à tout moment pendant que vous travaillez dessus même dans un nouveau projet, cela peut être déroutant si vous ne l'avez pas défini vous-même. Par exemple, cela a fonctionné et compilé et vous validez le code. Quelqu'un d'autre arrive le lendemain, checkout et il ne compile même pas car la dernière version a changé. Bien sûr, vous faites ce que vous voulez mais j'éviterais de l'utiliser pour cette raison (versionning).
Christophe Roussy

Réponses:

259

Importations pertinentes:

import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import java.io.IOException;

Usage:

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

EDIT (après la suggestion de Jules):

Comme la build()méthode renvoie un CloseableHttpClientqui est-a AutoClosable , vous pouvez placer la déclaration dans une instruction try-with-resources (Java 7+):

try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {

    // use httpClient (no need to close it explicitly)

} catch (IOException e) {

    // handle

}
hthserhs
la source
2
Vous utilisez la version inférieure à 4.3 (et cela devrait être Apache HTTPClient, pas Commons HTTPClient)
Alfishe
7
Notez que la valeur de retour est a CloseableHttpClient, que vous devez fermer après utilisation. Elle met en œuvre AutoCloseable, de sorte que vous pouvez l' utiliser dans un essai avec des ressources-déclaration en Java 7+: try (CloseableHttpClient httpclient = ...) { ... }.
Jules
2
CloseableHttpClient httpClient = HttpClientBuilder.create (). Build (); ce travail pour moi
Sameer Kazi
6
Question: Doit-on conserver l'instance HttpClientBuilder retournée par la create()méthode statique? Ou pouvons-nous simplement appeler create()chaque fois que nous en avons besoin? ... Btw, import org.apache.http.impl.client.HttpClientBuilderpour tous ceux qui en ont besoin. [N'aime pas les réponses sans instructions d'importation. Ne vous inquiétez pas, j'ai toujours voté pour :)]
ADTC
1
@HartmutPfitzinger utilise OkHttp sur Android. Ils ont foiré un client Apache Http fourchu, qui est maintenant hérité.
sschrass
59

À mon humble avis, la réponse acceptée est correcte mais manque un certain «enseignement» car il n'explique pas comment trouver la réponse. Pour toutes les classes obsolètes, regardez le JavaDoc (si vous ne l'avez pas, téléchargez-le ou allez en ligne ), il indiquera quelle classe utiliser pour remplacer l'ancien code. Bien sûr, cela ne vous dira pas tout, mais c'est un début. Exemple:

...
 *
 * @deprecated (4.3) use {@link HttpClientBuilder}.  <----- THE HINT IS HERE !
 */
@ThreadSafe
@Deprecated
public class DefaultHttpClient extends AbstractHttpClient {

Maintenant , vous avez la classe à utiliser, HttpClientBuildercar il n'y a pas de constructeur pour obtenir un constructeur exemple , vous pouvez deviner qu'il doit y avoir une méthode statique au lieu: create. Une fois que vous avez le constructeur, vous pouvez également deviner que, comme pour la plupart des constructeurs, il existe une méthode de construction , ainsi:

org.apache.http.impl.client.HttpClientBuilder.create().build();

Fermeture automatique:

Comme Jules l'a indiqué dans les commentaires, la classe retournée est implémentée java.io.Closable, donc si vous utilisez Java 7 ou supérieur, vous pouvez maintenant faire:

    try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {...}

L'avantage est que vous n'avez pas à vous occuper des finalement et des nulls.

Autres informations pertinentes

Assurez-vous également de lire sur le regroupement de connexions et de définir les délais d'expiration .

Christophe Roussy
la source
11

Les exemples d'Apache utilisent ceci:

CloseableHttpClient httpclient = HttpClients.createDefault();

La classe org.apache.http.impl.client.HttpClientsest là depuis la version 4.3.

Le code pour HttpClients.createDefault()est le même que la réponse acceptée ici.

IvanRF
la source
obtenir l'erreur "Causé par: java.lang.VerifyError: org / apache / http / conn / ssl / DefaultHostnameVerifier" lors de l'utilisation de HttpClient client = HttpClients.createDefault ();
Md Imran Choudhury
7

Il est devenu obsolète dans la version 4.3-alpha1que vous utilisez en raison de la LATESTspécification de version. Si vous jetez un oeil à la javadoc de la classe, il vous indique ce qu'il faut utiliser: HttpClientBuilder.

Dans la dernière version stable ( 4.2.3), le DefaultHttpClientn'est pas encore obsolète.

Zagyi
la source
Merci pour la réponse - Netbeans ne montre aucun JavaDocs pour aucun des trucs org.apache - mais je suppose que c'est un problème différent
base
Vous n'avez probablement pas les sources attachées à la bibliothèque. Je n'utilise pas Netbeans, mais je suppose qu'il existe un moyen de lui demander de télécharger les sources des dépendances.
zagyi
7

Essayez jcabi-http, qui est un client HTTP Java fluide, par exemple:

String html = new JdkRequest("https://www.google.com")
  .header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML)
  .fetch()
  .as(HttpResponse.class)
  .assertStatus(HttpURLConnection.HTTP_OK)
  .body();

Consultez également ce billet de blog: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html

yegor256
la source
4

Je suggérerais d'utiliser la méthode ci-dessous si vous essayez de lire uniquement les données json.

URL requestUrl=new URL(url);
URLConnection con = requestUrl.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb=new StringBuilder();
int cp;
try {
    while((cp=rd.read())!=-1){
    sb.append((char)cp);
  }
 catch(Exception e){
 }
 String json=sb.toString();
Anubhab
la source
La question dit DefaultHttpClientest obsolète et vous suggérez de l'utiliser dans votre réponse ...
base
Merci pour l'approche alternative. Je suis déjà allé avec la réponse acceptée, mais cela semble assez léger pour que je l'essaie la prochaine fois.
base
2

Utilisez HttpClientBuilder pour générer le HttpClient au lieu d'utiliser DefaultHttpClient

ex:

MinimalHttpClient httpclient = new HttpClientBuilder().build();

 // Prepare a request object
 HttpGet httpget = new HttpGet("http://www.apache.org/");
Arun P Johny
la source
Pourquoi new HttpClientBuilder()et pas HttpClientBuilder.create()?
ADTC
2

Vous pouvez ajouter la dépendance Maven suivante.

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.5.1</version>
    </dependency>

Vous pouvez utiliser l'importation suivante dans votre code java.

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGett;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.client.methods.HttpUriRequest;

Vous pouvez utiliser le bloc de code suivant dans votre code java.

HttpClient client = HttpClientBuilder.create().build();
HttpUriRequest httpUriRequest = new HttpGet("http://example.domain/someuri");

HttpResponse response = client.execute(httpUriRequest);
System.out.println("Response:"+response);
Garçon rouge
la source
Merci d'avoir pris le temps de répondre, mais en quoi est-ce différent de la réponse acceptée?
base
1
La plupart des réponses sont des codes psuedo, j'ai essayé de créer un code Java de base de bout en bout avec l'API Apache HTTP Client ainsi que la dépendance maven. Rien d'extraordinaire cependant.
Red Boy
1

C'est la solution que j'ai appliquée au problème que httpclient a abandonné dans cette version d'android 22

 public static String getContenxtWeb(String urlS) {
    String pagina = "", devuelve = "";
    URL url;
    try {
        url = new URL(urlS);
        HttpURLConnection conexion = (HttpURLConnection) url
                .openConnection();
        conexion.setRequestProperty("User-Agent",
                "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)");
        if (conexion.getResponseCode() == HttpURLConnection.HTTP_OK) {
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(conexion.getInputStream()));
            String linea = reader.readLine();
            while (linea != null) {
                pagina += linea;
                linea = reader.readLine();
            }
            reader.close();

            devuelve = pagina;
        } else {
            conexion.disconnect();
            return null;
        }
        conexion.disconnect();
        return devuelve;
    } catch (Exception ex) {
        return devuelve;
    }
}
Frutos Marquez
la source
-2

Pour le problème d'origine, je vous demanderais d'appliquer la logique ci-dessous:

 CloseableHttpClient httpClient = HttpClientBuilder.create().build();
 HttpPost httpPostRequest = new HttpPost();
Pra_A
la source