2009-08-31 36 views
343

En Java, ¿cómo redactar un mensaje de solicitud HTTP y enviarlo a un servidor web HTTP?¿Cómo enviar una solicitud HTTP en Java?

+27

[Hay un mini tutorial aquí en SO] (http: // stackoverflow.com/questions/2793150/how-to-use-java-net-urlconnection-to-fire-and-handle-http-requests). – BalusC

+0

http://java.sun.com/javase/6/docs/api/java/net/HttpURLConnection.html En particular, getHeaderField, getHeaderFieldKey y getContent –

+0

Puede usar la lib de JSoup (http://jsoup.org) ¡Hace exactamente lo que preguntas! Documento doc = Jsoup.connect ("http://en.wikipedia.org"). obtener(); (desde el sitio). Una forma más pitónica para Java. – user2007447

Respuesta

254

Puede usar java.net.HttpUrlConnection.

Ejemplo (from here), con mejoras. Incluido en caso de enlace roto:

public static String executePost(String targetURL, String urlParameters) { 
    HttpURLConnection connection = null; 

    try { 
    //Create connection 
    URL url = new URL(targetURL); 
    connection = (HttpURLConnection) url.openConnection(); 
    connection.setRequestMethod("POST"); 
    connection.setRequestProperty("Content-Type", 
     "application/x-www-form-urlencoded"); 

    connection.setRequestProperty("Content-Length", 
     Integer.toString(urlParameters.getBytes().length)); 
    connection.setRequestProperty("Content-Language", "en-US"); 

    connection.setUseCaches(false); 
    connection.setDoOutput(true); 

    //Send request 
    DataOutputStream wr = new DataOutputStream (
     connection.getOutputStream()); 
    wr.writeBytes(urlParameters); 
    wr.close(); 

    //Get Response 
    InputStream is = connection.getInputStream(); 
    BufferedReader rd = new BufferedReader(new InputStreamReader(is)); 
    StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+ 
    String line; 
    while ((line = rd.readLine()) != null) { 
     response.append(line); 
     response.append('\r'); 
    } 
    rd.close(); 
    return response.toString(); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    return null; 
    } finally { 
    if (connection != null) { 
     connection.disconnect(); 
    } 
    } 
} 
+2

Aquí hay otro bonito fragmento de código en reemplazo del Almanaque de Java: [HttpUrlConnection-Example] (http://www.xyzws.com/Javafaq/how-to-use-httpurlconnection-post-data-to-web-server/139) – GreenTurtle

+9

Poner un código real en esta respuesta ayudará a evitar la rotura del enlace ... – Cypher

202

De Oracle's java tutorial

import java.net.*; 
import java.io.*; 

public class URLConnectionReader { 
    public static void main(String[] args) throws Exception { 
     URL yahoo = new URL("http://www.yahoo.com/"); 
     URLConnection yc = yahoo.openConnection(); 
     BufferedReader in = new BufferedReader(
           new InputStreamReader(
           yc.getInputStream())); 
     String inputLine; 

     while ((inputLine = in.readLine()) != null) 
      System.out.println(inputLine); 
     in.close(); 
    } 
} 
+1

Lo extraño es que algunos servidores te responderán con extraño? caracteres (que parece un error de codificación relacionado con los encabezados de solicitud pero no) si no abre una secuencia de salida y la vacía primero. No tengo idea de por qué sucede esto, pero será genial si alguien puede explicar por qué? – Gorky

+1

@Gorky: Haga una nueva pregunta –

+51

Esto es demasiado ruido de línea para enviar una solicitud HTTP imo. Contraste a la biblioteca de solicitudes de Python: 'response = requests.get ('http://www.yahoo.com/')'; algo de brevedad similar debería ser posible en Java. –

59

Sé que otros recomendarán http-cliente de Apache, pero añade complejidad (es decir, más cosas que pueden salir mal) que rara vez garantizado Para una tarea simple, java.net.URL hará.

URL url = new URL("http://www.y.com/url"); 
InputStream is = url.openStream(); 
try { 
    /* Now read the retrieved document from the stream. */ 
    ... 
} finally { 
    is.close(); 
} 
+5

Eso no ayuda si quiere usar encabezados de solicitud, algo que es particularmente útil cuando se trata de sitios que solo responden de cierta manera a navegadores populares. – Jherico

+30

Puede usar los encabezados de solicitud usando URLConnection, pero el cartel no lo solicita; a juzgar por la pregunta, una respuesta simple es importante. – erickson

54

Apache HttpComponents. Los ejemplos para los dos módulos - HttpCore y HttpClient le ayudarán a comenzar de inmediato.

No es que HttpURLConnection es una mala elección, HttpComponents se resumen una gran cantidad de la tediosa codificación de distancia. Yo recomendaría esto, si realmente quiere soportar una gran cantidad de servidores HTTP/clientes con un código mínimo. Por cierto, HttpCore podría usarse para aplicaciones (clientes o servidores) con funcionalidad mínima, mientras que HttpClient se usará para clientes que requieren soporte para múltiples esquemas de autenticación, soporte de cookies, etc.

+2

FWIW, nuestro código comenzó con java.net.HttpURLConnection, pero cuando tuvimos que agregar SSL y solucionar algunos de los casos de uso extraños en nuestras intrincadas redes internas, se convirtió en un verdadero dolor de cabeza. Apache HttpComponents salvó el día. Nuestro proyecto actualmente todavía utiliza un híbrido feo, con algunos adaptadores poco fiables para convertir java.net.URLs a los URI que utiliza HttpComponents. Refactorizo ​​esos regularmente. La única vez que el código de HttpComponents resultó significativamente más complicado fue para analizar las fechas desde un encabezado. Pero la [solución] (http://stackoverflow.com/a/1930240/1450294) es simple. –

7

Hay un gran enlace para enviar un solicitud POST here por ejemplo Depot ::

try { 
    // Construct data 
    String data = URLEncoder.encode("key1", "UTF-8") + "=" + URLEncoder.encode("value1", "UTF-8"); 
    data += "&" + URLEncoder.encode("key2", "UTF-8") + "=" + URLEncoder.encode("value2", "UTF-8"); 

    // Send data 
    URL url = new URL("http://hostname:80/cgi"); 
    URLConnection conn = url.openConnection(); 
    conn.setDoOutput(true); 
    OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); 
    wr.write(data); 
    wr.flush(); 

    // Get the response 
    BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
    String line; 
    while ((line = rd.readLine()) != null) { 
     // Process line... 
    } 
    wr.close(); 
    rd.close(); 
} catch (Exception e) { 
} 

Si desea enviar una petición GET puede modificar ligeramente el código para satisfacer sus necesidades. Específicamente, debe agregar los parámetros dentro del constructor de la URL. Luego, también comente este wr.write(data);

Una cosa que no está escrita y debe tener cuidado, es el tiempo de espera. Especialmente si desea usarlo en WebServices, debe establecer tiempos de espera, de lo contrario, el código anterior esperará indefinidamente o durante mucho tiempo al menos y es algo que presumiblemente no desea.

Tiempos de espera se configuran como esto conn.setReadTimeout(2000); el parámetro de entrada es en milisegundos

12

Esto le ayudará. No se olvide de agregar el JAR HttpClient.jar al classpath.

import java.io.FileOutputStream; 
import java.io.IOException; 

import org.apache.commons.httpclient.HttpClient; 
import org.apache.commons.httpclient.HttpStatus; 
import org.apache.commons.httpclient.NameValuePair; 
import org.apache.commons.httpclient.methods.PostMethod; 

public class MainSendRequest { 

    static String url = 
     "http://localhost:8080/HttpRequestSample/RequestSend.jsp"; 

    public static void main(String[] args) { 

     //Instantiate an HttpClient 
     HttpClient client = new HttpClient(); 

     //Instantiate a GET HTTP method 
     PostMethod method = new PostMethod(url); 
     method.setRequestHeader("Content-type", 
       "text/xml; charset=ISO-8859-1"); 

     //Define name-value pairs to set into the QueryString 
     NameValuePair nvp1= new NameValuePair("firstName","fname"); 
     NameValuePair nvp2= new NameValuePair("lastName","lname"); 
     NameValuePair nvp3= new NameValuePair("email","[email protected]"); 

     method.setQueryString(new NameValuePair[]{nvp1,nvp2,nvp3}); 

     try{ 
      int statusCode = client.executeMethod(method); 

      System.out.println("Status Code = "+statusCode); 
      System.out.println("QueryString>>> "+method.getQueryString()); 
      System.out.println("Status Text>>>" 
        +HttpStatus.getStatusText(statusCode)); 

      //Get data as a String 
      System.out.println(method.getResponseBodyAsString()); 

      //OR as a byte array 
      byte [] res = method.getResponseBody(); 

      //write to file 
      FileOutputStream fos= new FileOutputStream("donepage.html"); 
      fos.write(res); 

      //release connection 
      method.releaseConnection(); 
     } 
     catch(IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+1

En serio, realmente me gusta Java, pero ¿qué le pasa a esa estúpida lista o matriz 'NameValuePair'. ¿Por qué no un simple 'Map '? Tanto código repetitivo para casos de uso tan simples ... – Joffrey

+2

@Joffrey Maps por definición tiene 1 clave por valor, significa: '¡Un mapa no puede contener claves duplicadas! Pero los parámetros de HTTP pueden tener claves duplicadas. – Ben

9

Es posible utilizar Toma para esto como

String host = "www.yourhost.com"; 
Socket socket = new Socket(host, 80); 
String request = "GET/HTTP/1.0\r\n\r\n"; 
OutputStream os = socket.getOutputStream(); 
os.write(request.getBytes()); 
os.flush(); 

InputStream is = socket.getInputStream(); 
int ch; 
while((ch=is.read())!= -1) 
    System.out.print((char)ch); 
socket.close();  
+0

@laksys ¿por qué debería ser '\ r \ n' en lugar de' \ n'? – CuriousGuy

+0

@CuriousGuy mira este enlace http://programmers.stackexchange.com/questions/29075/difference-between-n-and-r-n – laksys

20

Aquí es un programa completo de Java 7:

class GETHTTPResource { 
    public static void main(String[] args) throws Exception { 
    try (java.util.Scanner s = new java.util.Scanner(new java.net.URL("http://tools.ietf.org/rfc/rfc768.txt").openStream())) { 
     System.out.println(s.useDelimiter("\\A").next()); 
    } 
    } 
} 

El nuevo Auto-cierra el escáner try-con-recursos, lo cual cerrará automáticamente el InputStream.

+0

Tienes una excepción no controlada aquí. Esto es Java, y tiene 500 excepciones para manejar por cada línea de código :) – Ska

+0

@Ska No hay excepción no controlada. 'main()' arroja Exception, que abarca la excepción MalformedURLException y la IOException. – jerzy

12

Google java http client tiene buena API para peticiones http. Puede agregar fácilmente el soporte JSON, etc. Aunque por simple solicitud, podría ser excesivo.

import com.google.api.client.http.GenericUrl; 
import com.google.api.client.http.HttpRequest; 
import com.google.api.client.http.HttpResponse; 
import com.google.api.client.http.HttpTransport; 
import com.google.api.client.http.javanet.NetHttpTransport; 
import java.io.IOException; 
import java.io.InputStream; 

public class Network { 

    static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); 

    public void getRequest(String reqUrl) throws IOException { 
     GenericUrl url = new GenericUrl(reqUrl); 
     HttpRequest request = HTTP_TRANSPORT.createRequestFactory().buildGetRequest(url); 
     HttpResponse response = request.execute(); 
     System.out.println(response.getStatusCode()); 

     InputStream is = response.getContent(); 
     int ch; 
     while ((ch = is.read()) != -1) { 
      System.out.print((char) ch); 
     } 
     response.disconnect(); 
    } 
} 
+0

¿Qué quiere decir con 'transporte'? – raspi

+0

Lo siento, debería haber sido 'HTTP_TRANSPORT', he editado la respuesta. – Tombart

+0

¿por qué HttpResponse no se puede cerrar automáticamente? ¿Cuál es la diferencia de esto y para trabajar con CloseableHttpClient de Apache? –

Cuestiones relacionadas