Java HttpClient en desuso: ¿qué tan difícil puede ser?

172

Todo lo que intento hacer es descargar algunos JSON y deserializarlos en un objeto. Todavía no he llegado a descargar el JSON.

Casi todos los ejemplos de HttpClient que puedo encontrar, incluidos los del sitio apache, se parecen a ...

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

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

Sin embargo, Netbeans me dice que DefaultHttpClientestá en desuso. He intentado buscar en Google DefaultHttpClient deprecatedy en tantas otras variaciones en las que puedo pensar y no puedo encontrar ningún resultado útil, por lo que obviamente me falta algo.

¿Cuál es la forma correcta de Java7 para descargar el contenido de una página web? ¿Realmente no hay un Http Client decente como parte del lenguaje? Me parece difícil de creer.

Mi dependencia de Maven para esto es ...

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>LATEST</version>
    <type>jar</type>
</dependency>
Básico
fuente
2
NetBeans te está diciendo mal, o estás malinterpretando algo. DefaultHttpClientDefinitivamente no está en desuso. ¿Qué versión especificó en su POM?
Percepción
8
en 4.3-alpha1 parece estar en desuso
Arun P Johny
3
Tienes razón, la API httpclient es un desastre
Hans Westerbeek
2
Le recomendaría que configure la versión con algún número de versión principal en lugar de ÚLTIMO. Esto le permitirá controlar manualmente el proceso de actualización y no dejar que Maven decida por usted.
Christophe Roussy
1
@ Básico puede cambiar en cualquier momento mientras trabaja en él, incluso en un nuevo proyecto, esto puede ser confuso si no lo configuró usted mismo. Por ejemplo, funcionó y se compiló y confirmó el código. Alguien más llega al día siguiente, finaliza la compra y ni siquiera se compila porque la ÚLTIMA versión cambió. Por supuesto que haces lo que quieres, pero evitaría usarlo por este motivo (versionado).
Christophe Roussy

Respuestas:

259

Importaciones relevantes:

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

Uso:

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

EDITAR (después de la sugerencia de Jules):

A medida que el build()método devuelve un CloseableHttpClientque es-a AutoClosable , puede colocar la declaración en una declaración de prueba con recursos (Java 7+):

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

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

} catch (IOException e) {

    // handle

}
hthserhs
fuente
2
Está utilizando la versión inferior a 4.3 (y debería ser Apache HTTPClient, no Commons HTTPClient)
Alfishe
77
Tenga en cuenta que el valor de retorno es a CloseableHttpClient, que debe cerrar después de su uso. Pone en práctica AutoCloseable, por lo que se puede utilizar en una sentencia try-con-recursos en Java 7+: try (CloseableHttpClient httpclient = ...) { ... }.
Jules
2
CloseableHttpClient httpClient = HttpClientBuilder.create (). Build (); esto funciona para mí
Sameer Kazi
66
Pregunta: ¿Deberíamos conservar la instancia de HttpClientBuilder que devuelve el create()método estático? ¿O podemos llamar create()siempre que lo necesitemos? ... Por cierto, import org.apache.http.impl.client.HttpClientBuilderpara cualquiera que lo necesite. [No le gustan las respuestas sin declaraciones de importación. No se preocupe, todavía voté :)]
ADTC
1
@HartmutPfitzinger usa OkHttp en Android. Se equivocaron con un Apache Http Client bifurcado, que ahora es heredado.
sschrass
59

En mi humilde opinión, la respuesta aceptada es correcta, pero se pierde un poco de "enseñanza", ya que no explica cómo llegar a la respuesta. Para todas las clases desaprobadas, mire el JavaDoc (si no lo tiene, descárguelo o conéctese a Internet ), le indicará qué clase usar para reemplazar el código anterior. Por supuesto, no te dirá todo, pero este es un comienzo. Ejemplo:

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

Ahora usted tiene la clase que se utiliza, HttpClientBuildercomo no hay ningún constructor para obtener un constructor de instancia puede adivinar que debe haber un método estático en su lugar: create. Una vez que tenga el constructor, también puede adivinar que, como para la mayoría de los constructores, hay un método de compilación , por lo tanto:

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

Autocerrable:

Como Jules insinuó en los comentarios, la clase devuelta se implementa java.io.Closable, por lo que si usa Java 7 o superior, ahora puede hacer:

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

La ventaja es que no tiene que lidiar finalmente con nulos.

Otra información relevante

También asegúrese de leer sobre la agrupación de conexiones y establecer los tiempos de espera .

Christophe Roussy
fuente
11

Los ejemplos de Apache usan esto:

CloseableHttpClient httpclient = HttpClients.createDefault();

La clase org.apache.http.impl.client.HttpClientsestá allí desde la versión 4.3.

El código para HttpClients.createDefault()es el mismo que la respuesta aceptada aquí.

IvanRF
fuente
obtener el error "Causado por: java.lang.VerifyError: org / apache / http / conn / ssl / DefaultHostnameVerifier" cuando se usa HttpClient client = HttpClients.createDefault ();
Md Imran Choudhury
7

Se desactivó en la versión 4.3-alpha1que usa debido a la LATESTespecificación de la versión. Si se echa un vistazo en el javadoc de la clase, le dice lo que debe utilizar en su lugar: HttpClientBuilder.

En la última versión estable ( 4.2.3) DefaultHttpClienttodavía no está en desuso.

zagyi
fuente
Gracias por la respuesta: Netbeans no muestra ningún JavaDoc para ninguna de las cosas de org.apache, pero supongo que es un problema diferente
Básico
Probablemente no tenga las fuentes conectadas a la biblioteca. No uso Netbeans, pero creo que hay una manera de pedirle que descargue las fuentes de las dependencias.
zagyi
7

Pruebe jcabi-http, que es un cliente HTTP Java fluido, por ejemplo:

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

Consulte también esta publicación de blog: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html

yegor256
fuente
4

Sugeriría usar el siguiente método si está tratando de leer solo los datos 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
fuente
Las preguntas dice DefaultHttpClientestá en desuso y que sugieren el uso en su respuesta ...
Básico
Gracias por el enfoque alternativo. Ya he respondido con la respuesta acertada, pero esto parece lo suficientemente ligero como para intentarlo la próxima vez.
Básico
2

Use HttpClientBuilder para construir el HttpClient en lugar de usar DefaultHttpClient

ex:

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

 // Prepare a request object
 HttpGet httpget = new HttpGet("http://www.apache.org/");
Arun P Johny
fuente
¿Por qué new HttpClientBuilder()y no HttpClientBuilder.create()?
ADTC
2

Puede agregar la siguiente dependencia de Maven.

    <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>

Puede usar la siguiente importación en su código 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;

Puede usar el siguiente bloque de código en su código java.

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

HttpResponse response = client.execute(httpUriRequest);
System.out.println("Response:"+response);
Chico rojo
fuente
Gracias por tomarse el tiempo para responder, pero ¿en qué se diferencia esto de la respuesta aceptada?
Básico
1
La mayoría de las respuestas son códigos psuedo, intenté hacer un código Java de trabajo básico de extremo a extremo con la API de cliente HTTP Apache junto con la dependencia de Maven. Sin embargo, nada genial.
Red Boy
1

Esta es la solución que he aplicado al problema que httpclient desaprobó en esta versión de 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
fuente
-2

Para el problema original, le pediría que aplique la siguiente lógica:

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