Domanda Come utilizzare java.net.URLConnection per attivare e gestire le richieste HTTP


Uso di java.net.URLConnection viene chiesto abbastanza spesso qui, e il Tutorial Oracle è pure conciso su di esso.

Quel tutorial in pratica mostra solo come lanciare una richiesta GET e leggere la risposta. Non spiega da nessuna parte come usarlo per eseguire tra l'altro una richiesta POST, impostare intestazioni di richieste, leggere le intestazioni di risposta, gestire i cookie, inviare un modulo HTML, caricare un file, ecc.

Quindi, come posso usare java.net.URLConnection sparare e gestire richieste HTTP "avanzate"?


1758


origine


risposte:


Innanzitutto una dichiarazione di non responsabilità: i frammenti di codice pubblicati sono tutti esempi di base. Dovrai gestire banale IOExceptions e RuntimeExceptions come NullPointerException, ArrayIndexOutOfBoundsException e ti consoli.


Preparazione

Per prima cosa dobbiamo conoscere almeno l'URL e il set di caratteri. I parametri sono opzionali e dipendono dai requisiti funzionali.

String url = "http://example.com";
String charset = "UTF-8";  // Or in Java 7 and later, use the constant: java.nio.charset.StandardCharsets.UTF_8.name()
String param1 = "value1";
String param2 = "value2";
// ...

String query = String.format("param1=%s&param2=%s", 
     URLEncoder.encode(param1, charset), 
     URLEncoder.encode(param2, charset));

I parametri della query devono essere in name=value formato ed essere concatenato da &. Normalmente lo faresti anche tu URL-encode i parametri di query con il set di caratteri specificato usando URLEncoder#encode().

Il String#format() è solo per comodità. Lo preferisco quando mi serve l'operatore di concatenazione delle stringhe + più di due volte.


Sparare a HTTP GET richiesta con (facoltativamente) parametri di ricerca

È un compito banale. È il metodo di richiesta predefinito.

URLConnection connection = new URL(url + "?" + query).openConnection();
connection.setRequestProperty("Accept-Charset", charset);
InputStream response = connection.getInputStream();
// ...

Qualsiasi stringa di query deve essere concatenata all'URL utilizzando ?. Il Accept-Charset l'intestazione può suggerire al server la codifica dei parametri. Se non si invia alcuna stringa di interrogazione, è possibile uscire da Accept-Charset colpo di testa. Se non è necessario impostare alcuna intestazione, è possibile utilizzare anche il URL#openStream() metodo di scelta rapida.

InputStream response = new URL(url).openStream();
// ...

Ad ogni modo, se l'altro lato è un HttpServlet, quindi suo doGet() verrà chiamato il metodo e i parametri saranno disponibili da HttpServletRequest#getParameter().

A scopo di test, è possibile stampare il corpo della risposta su stdout come di seguito:

try (Scanner scanner = new Scanner(response)) {
    String responseBody = scanner.useDelimiter("\\A").next();
    System.out.println(responseBody);
}

Sparare a HTTP POST richiesta con parametri di query

Impostazione del URLConnection#setDoOutput() a true imposta implicitamente il metodo di richiesta su POST. Il POST HTTP standard come i moduli Web è di tipo application/x-www-form-urlencoded in cui la stringa di query viene scritta nel corpo della richiesta.

URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true); // Triggers POST.
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);

try (OutputStream output = connection.getOutputStream()) {
    output.write(query.getBytes(charset));
}

InputStream response = connection.getInputStream();
// ...

Nota: ogni volta che desideri inviare un modulo HTML a livello di programmazione, non dimenticare di prendere il name=value coppie di qualsiasi <input type="hidden"> elementi nella stringa di query e, naturalmente, anche il name=value coppia di <input type="submit"> elemento che si desidera "premere" a livello di codice (perché di solito è stato usato sul lato server per distinguere se un pulsante è stato premuto e, in tal caso, quale).

Puoi anche lanciare il risultato ottenuto URLConnection a HttpURLConnection e usa il suo HttpURLConnection#setRequestMethod() anziché. Ma se stai cercando di utilizzare la connessione per l'output, devi comunque impostarlo URLConnection#setDoOutput() a true.

HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection();
httpConnection.setRequestMethod("POST");
// ...

Ad ogni modo, se l'altro lato è un HttpServlet, quindi suo doPost() verrà chiamato il metodo e i parametri saranno disponibili da HttpServletRequest#getParameter().


Attiva effettivamente la richiesta HTTP

È possibile attivare esplicitamente la richiesta HTTP con URLConnection#connect(), ma la richiesta verrà automaticamente attivata su richiesta quando si desidera ottenere qualsiasi informazione sulla risposta HTTP, come ad esempio il corpo della risposta URLConnection#getInputStream()e così via. Gli esempi sopra fanno esattamente questo, quindi il connect() la chiamata è infatti superflua.


Raccolta di informazioni sulla risposta HTTP

  1. Stato della risposta HTTP:

    Avete bisogno di un HttpURLConnection Qui. Provalo prima se necessario.

    int status = httpConnection.getResponseCode();
    
  2. Intestazioni di risposta HTTP:

    for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
        System.out.println(header.getKey() + "=" + header.getValue());
    }
    
  3. Codifica della risposta HTTP:

    Quando il Content-Type contiene a charset parametro, quindi il corpo della risposta è probabilmente basato sul testo e vorremmo elaborare il corpo della risposta con la codifica dei caratteri specificata sul lato server quindi.

    String contentType = connection.getHeaderField("Content-Type");
    String charset = null;
    
    for (String param : contentType.replace(" ", "").split(";")) {
        if (param.startsWith("charset=")) {
            charset = param.split("=", 2)[1];
            break;
        }
    }
    
    if (charset != null) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(response, charset))) {
            for (String line; (line = reader.readLine()) != null;) {
                // ... System.out.println(line) ?
            }
        }
    } else {
        // It's likely binary content, use InputStream/OutputStream.
    }
    

Mantenimento della sessione

La sessione lato server è solitamente supportata da un cookie. Alcuni moduli Web richiedono l'accesso e / o il tracciamento di una sessione. Puoi usare il CookieHandler API per mantenere i cookie. Devi preparare un CookieManager con un CookiePolicy di ACCEPT_ALL prima di inviare tutte le richieste HTTP.

// First set the default cookie manager.
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

// All the following subsequent URLConnections will use the same cookie manager.
URLConnection connection = new URL(url).openConnection();
// ...

connection = new URL(url).openConnection();
// ...

connection = new URL(url).openConnection();
// ...

Si noti che questo è noto non sempre funziona correttamente in tutte le circostanze. Se fallisce per te, allora è meglio raccogliere e impostare manualmente le intestazioni dei cookie. Fondamentalmente hai bisogno di afferrare tutto Set-Cookie intestazioni dalla risposta del login o del primo GET richiedere e quindi passare questo attraverso le richieste successive.

// Gather all cookies on the first request.
URLConnection connection = new URL(url).openConnection();
List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
// ...

// Then use the same cookies on all subsequent requests.
connection = new URL(url).openConnection();
for (String cookie : cookies) {
    connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
}
// ...

Il split(";", 2)[0] è lì per sbarazzarsi di attributi cookie che sono irrilevanti per il lato server come expires, path, ecc. In alternativa, potresti anche usare cookie.substring(0, cookie.indexOf(';')) invece di split().


Modalità di streaming

Il HttpURLConnection per impostazione predefinita il buffer di intero richiedere il corpo prima di inviarlo effettivamente, indipendentemente dal fatto che tu abbia impostato da solo una durata del contenuto fissa connection.setRequestProperty("Content-Length", contentLength);. Questo potrebbe causare OutOfMemoryExceptions ogni volta che si inviano contemporaneamente richieste POST di grandi dimensioni (ad esempio caricamento di file). Per evitare questo, ti piacerebbe impostare il HttpURLConnection#setFixedLengthStreamingMode().

httpConnection.setFixedLengthStreamingMode(contentLength);

Ma se la lunghezza del contenuto non è realmente nota in anticipo, è possibile utilizzare la modalità di streaming chunked impostando il comando HttpURLConnection#setChunkedStreamingMode() di conseguenza. Questo imposterà l'HTTP Transfer-Encoding intestazione a chunked che costringerà il corpo della richiesta a essere inviato in blocchi. L'esempio seguente invierà il corpo in blocchi di 1 KB.

httpConnection.setChunkedStreamingMode(1024);

User-Agent

Può succedere una richiesta restituisce una risposta inaspettata, mentre funziona perfettamente con un browser web reale. Il lato server probabilmente blocca le richieste in base a User-Agent richiesta intestazione. Il URLConnection per impostazione predefinita verrà impostato su Java/1.6.0_19 dove l'ultima parte è ovviamente la versione di JRE. È possibile ignorare questo come segue:

connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); // Do as if you're using Chrome 41 on Windows 7.

Utilizzare la stringa User-Agent da a browser recente.


Gestione degli errori

Se il codice di risposta HTTP è 4nn (Errore client) o 5nn (Errore del server), quindi si consiglia di leggere il HttpURLConnection#getErrorStream() per vedere se il server ha inviato informazioni utili sull'errore.

InputStream error = ((HttpURLConnection) connection).getErrorStream();

Se il codice di risposta HTTP è -1, qualcosa è andato storto con la gestione della connessione e della risposta. Il HttpURLConnection l'implementazione è nei vecchi JRE un po 'buggy con il mantenimento delle connessioni in vita. Potresti voler disattivarlo impostando il http.keepAlive proprietà di sistema a false. Puoi farlo a livello di codice all'inizio della tua applicazione:

System.setProperty("http.keepAlive", "false");

Caricamento di file

Normalmente useresti multipart/form-data codifica per contenuti POST misti (dati binari e di carattere). La codifica è più in dettaglio descritta in RFC2388.

String param = "value";
File textFile = new File("/path/to/file.txt");
File binaryFile = new File("/path/to/file.bin");
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

try (
    OutputStream output = connection.getOutputStream();
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
) {
    // Send normal param.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
    writer.append(CRLF).append(param).append(CRLF).flush();

    // Send text file.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF);
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); // Text file itself must be saved in this charset!
    writer.append(CRLF).flush();
    Files.copy(textFile.toPath(), output);
    output.flush(); // Important before continuing with writer!
    writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.

    // Send binary file.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
    writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getName())).append(CRLF);
    writer.append("Content-Transfer-Encoding: binary").append(CRLF);
    writer.append(CRLF).flush();
    Files.copy(binaryFile.toPath(), output);
    output.flush(); // Important before continuing with writer!
    writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.

    // End of multipart/form-data.
    writer.append("--" + boundary + "--").append(CRLF).flush();
}

Se l'altro lato è un HttpServlet, quindi suo doPost() il metodo verrà chiamato e le parti saranno disponibili da HttpServletRequest#getPart() (nota, quindi non  getParameter() e così via!). Il getPart() il metodo è tuttavia relativamente nuovo, è introdotto in Servlet 3.0 (Glassfish 3, Tomcat 7, ecc.). Prima di Servlet 3.0, la scelta migliore è l'utilizzo Apache Commons FileUpload analizzare a multipart/form-data richiesta. Vedi anche questa risposta per esempi di entrambi gli approcci FileUpload e Servelt 3.0.


Gestione di siti HTTPS non affidabili o mal configurati

A volte devi connettere un URL HTTPS, forse perché stai scrivendo un web raschietto. In tal caso, è probabile che faccia a faccia a javax.net.ssl.SSLException: Not trusted server certificate su alcuni siti HTTPS che non mantengono aggiornati i loro certificati SSL o a java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found o javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name su alcuni siti HTTPS configurati in modo errato.

Il seguente one-time-run static l'inizializzatore nella classe Web raschietto dovrebbe fare HttpsURLConnection più indulgente riguardo a quei siti HTTPS e quindi non gettare più queste eccezioni.

static {
    TrustManager[] trustAllCertificates = new TrustManager[] {
        new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null; // Not relevant.
            }
            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                // Do nothing. Just allow them all.
            }
            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                // Do nothing. Just allow them all.
            }
        }
    };

    HostnameVerifier trustAllHostnames = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true; // Just allow them all.
        }
    };

    try {
        System.setProperty("jsse.enableSNIExtension", "false");
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCertificates, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(trustAllHostnames);
    }
    catch (GeneralSecurityException e) {
        throw new ExceptionInInitializerError(e);
    }
}

Ultime parole

Il Apache HttpComponents HttpClient è tanto più comodo in tutto questo :)


Analisi ed estrazione di HTML

Se tutto ciò che vuoi è l'analisi e l'estrazione di dati da HTML, meglio usare un parser HTML come Jsoup


2524



Quando si lavora con HTTP è quasi sempre più utile fare riferimento HttpURLConnection piuttosto che la classe base URLConnection (da URLConnection è una classe astratta quando chiedi URLConnection.openConnection() su un URL HTTP è quello che tornerai comunque).

Quindi puoi invece fare affidamento URLConnection#setDoOutput(true) impostare implicitamente il metodo di richiesta su INVIARE invece httpURLConnection.setRequestMethod("POST") che alcuni potrebbero trovare più naturali (e che consente anche di specificare altri metodi di richiesta come METTERE, ELIMINA, ...).

Fornisce anche utili costanti HTTP in modo che tu possa fare:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

83



Ispirato da questa e da altre domande su SO, ho creato un open source minimo basic-http-client che incarna la maggior parte delle tecniche trovate qui.

google-http-java-client è anche una grande risorsa open source.


48



Ci sono 2 opzioni che puoi utilizzare con gli hit URL HTTP: GET / POST

Richiesta GET: -

HttpURLConnection.setFollowRedirects(true); // defaults to true

String url = "https://name_of_the_url";
URL request_url = new URL(url);
HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection();
http_conn.setConnectTimeout(100000);
http_conn.setReadTimeout(100000);
http_conn.setInstanceFollowRedirects(true);
System.out.println(String.valueOf(http_conn.getResponseCode()));

Richiesta POST: -

HttpURLConnection.setFollowRedirects(true); // defaults to true

String url = "https://name_of_the_url"
URL request_url = new URL(url);
HttpURLConnection http_conn = (HttpURLConnection)request_url.openConnection();
http_conn.setConnectTimeout(100000);
http_conn.setReadTimeout(100000);
http_conn.setInstanceFollowRedirects(true);
http_conn.setDoOutput(true);
PrintWriter out = new PrintWriter(http_conn.getOutputStream());
if (urlparameter != null) {
   out.println(urlparameter);
}
out.close();
out = null;
System.out.println(String.valueOf(http_conn.getResponseCode()));

21



Ti suggerisco di dare un'occhiata al codice kevinsawicki / http-request, è fondamentalmente un involucro in cima HttpUrlConnection fornisce un'API molto più semplice nel caso in cui desideri semplicemente effettuare le richieste in questo momento o puoi dare un'occhiata alle fonti (non è troppo grande) per dare un'occhiata a come vengono gestite le connessioni.

Esempio: Crea un GET richiesta con tipo di contenuto application/json e alcuni parametri di query:

// GET http://google.com?q=baseball%20gloves&size=100
String response = HttpRequest.get("http://google.com", true, "q", "baseball gloves", "size", 100)
        .accept("application/json")
        .body();
System.out.println("Response was: " + response);

19



Sono stato anche molto ispirato da questa risposta.

Sono spesso in progetti in cui ho bisogno di fare un po 'di HTTP, e potrei non voler portare molte dipendenze di terze parti (che portano in altri e così via e così via, ecc.)

Ho iniziato a scrivere le mie utility basandomi su alcune di queste conversazioni (non tutte le operazioni):

package org.boon.utils;


import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;

import static org.boon.utils.IO.read;

public class HTTP {

Quindi ci sono solo un mucchio o metodi statici.

public static String get(
        final String url) {

    Exceptions.tryIt(() -> {
        URLConnection connection;
        connection = doGet(url, null, null, null);
        return extractResponseString(connection);
    });
    return null;
}

public static String getWithHeaders(
        final String url,
        final Map<String, ? extends Object> headers) {
    URLConnection connection;
    try {
        connection = doGet(url, headers, null, null);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}

public static String getWithContentType(
        final String url,
        final Map<String, ? extends Object> headers,
        String contentType) {
    URLConnection connection;
    try {
        connection = doGet(url, headers, contentType, null);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}
public static String getWithCharSet(
        final String url,
        final Map<String, ? extends Object> headers,
        String contentType,
        String charSet) {
    URLConnection connection;
    try {
        connection = doGet(url, headers, contentType, charSet);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}

Quindi pubblica ...

public static String postBody(
        final String url,
        final String body) {
    URLConnection connection;
    try {
        connection = doPost(url, null, "text/plain", null, body);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}

public static String postBodyWithHeaders(
        final String url,
        final Map<String, ? extends Object> headers,
        final String body) {
    URLConnection connection;
    try {
        connection = doPost(url, headers, "text/plain", null, body);
        return extractResponseString(connection);
    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }
}



public static String postBodyWithContentType(
        final String url,
        final Map<String, ? extends Object> headers,
        final String contentType,
        final String body) {

    URLConnection connection;
    try {
        connection = doPost(url, headers, contentType, null, body);


        return extractResponseString(connection);


    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }


}


public static String postBodyWithCharset(
        final String url,
        final Map<String, ? extends Object> headers,
        final String contentType,
        final String charSet,
        final String body) {

    URLConnection connection;
    try {
        connection = doPost(url, headers, contentType, charSet, body);


        return extractResponseString(connection);


    } catch (Exception ex) {
        Exceptions.handle(ex);
        return null;
    }


}

private static URLConnection doPost(String url, Map<String, ? extends Object> headers,
                                    String contentType, String charset, String body
                                    ) throws IOException {
    URLConnection connection;/* Handle output. */
    connection = new URL(url).openConnection();
    connection.setDoOutput(true);
    manageContentTypeHeaders(contentType, charset, connection);

    manageHeaders(headers, connection);


    IO.write(connection.getOutputStream(), body, IO.CHARSET);
    return connection;
}

private static void manageHeaders(Map<String, ? extends Object> headers, URLConnection connection) {
    if (headers != null) {
        for (Map.Entry<String, ? extends Object> entry : headers.entrySet()) {
            connection.setRequestProperty(entry.getKey(), entry.getValue().toString());
        }
    }
}

private static void manageContentTypeHeaders(String contentType, String charset, URLConnection connection) {
    connection.setRequestProperty("Accept-Charset", charset == null ? IO.CHARSET : charset);
    if (contentType!=null && !contentType.isEmpty()) {
        connection.setRequestProperty("Content-Type", contentType);
    }
}

private static URLConnection doGet(String url, Map<String, ? extends Object> headers,
                                    String contentType, String charset) throws IOException {
    URLConnection connection;/* Handle output. */
    connection = new URL(url).openConnection();
    manageContentTypeHeaders(contentType, charset, connection);

    manageHeaders(headers, connection);

    return connection;
}

private static String extractResponseString(URLConnection connection) throws IOException {
/* Handle input. */
    HttpURLConnection http = (HttpURLConnection)connection;
    int status = http.getResponseCode();
    String charset = getCharset(connection.getHeaderField("Content-Type"));

    if (status==200) {
        return readResponseBody(http, charset);
    } else {
        return readErrorResponseBody(http, status, charset);
    }
}

private static String readErrorResponseBody(HttpURLConnection http, int status, String charset) {
    InputStream errorStream = http.getErrorStream();
    if ( errorStream!=null ) {
        String error = charset== null ? read( errorStream ) :
            read( errorStream, charset );
        throw new RuntimeException("STATUS CODE =" + status + "\n\n" + error);
    } else {
        throw new RuntimeException("STATUS CODE =" + status);
    }
}

private static String readResponseBody(HttpURLConnection http, String charset) throws IOException {
    if (charset != null) {
        return read(http.getInputStream(), charset);
    } else {
        return read(http.getInputStream());
    }
}

private static String getCharset(String contentType) {
    if (contentType==null)  {
        return null;
    }
    String charset = null;
    for (String param : contentType.replace(" ", "").split(";")) {
        if (param.startsWith("charset=")) {
            charset = param.split("=", 2)[1];
            break;
        }
    }
    charset = charset == null ?  IO.CHARSET : charset;

    return charset;
}

Bene hai capito l'idea ....

Ecco i test:

static class MyHandler implements HttpHandler {
    public void handle(HttpExchange t) throws IOException {

        InputStream requestBody = t.getRequestBody();
        String body = IO.read(requestBody);
        Headers requestHeaders = t.getRequestHeaders();
        body = body + "\n" + copy(requestHeaders).toString();
        t.sendResponseHeaders(200, body.length());
        OutputStream os = t.getResponseBody();
        os.write(body.getBytes());
        os.close();
    }
}


@Test
public void testHappy() throws Exception {

    HttpServer server = HttpServer.create(new InetSocketAddress(9212), 0);
    server.createContext("/test", new MyHandler());
    server.setExecutor(null); // creates a default executor
    server.start();

    Thread.sleep(10);


    Map<String,String> headers = map("foo", "bar", "fun", "sun");

    String response = HTTP.postBodyWithContentType("http://localhost:9212/test", headers, "text/plain", "hi mom");

    System.out.println(response);

    assertTrue(response.contains("hi mom"));
    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));


    response = HTTP.postBodyWithCharset("http://localhost:9212/test", headers, "text/plain", "UTF-8", "hi mom");

    System.out.println(response);

    assertTrue(response.contains("hi mom"));
    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));

    response = HTTP.postBodyWithHeaders("http://localhost:9212/test", headers, "hi mom");

    System.out.println(response);

    assertTrue(response.contains("hi mom"));
    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));


    response = HTTP.get("http://localhost:9212/test");

    System.out.println(response);


    response = HTTP.getWithHeaders("http://localhost:9212/test", headers);

    System.out.println(response);

    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));



    response = HTTP.getWithContentType("http://localhost:9212/test", headers, "text/plain");

    System.out.println(response);

    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));



    response = HTTP.getWithCharSet("http://localhost:9212/test", headers, "text/plain", "UTF-8");

    System.out.println(response);

    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));

    Thread.sleep(10);

    server.stop(0);


}

@Test
public void testPostBody() throws Exception {

    HttpServer server = HttpServer.create(new InetSocketAddress(9220), 0);
    server.createContext("/test", new MyHandler());
    server.setExecutor(null); // creates a default executor
    server.start();

    Thread.sleep(10);


    Map<String,String> headers = map("foo", "bar", "fun", "sun");

    String response = HTTP.postBody("http://localhost:9220/test", "hi mom");

    assertTrue(response.contains("hi mom"));


    Thread.sleep(10);

    server.stop(0);


}

@Test(expected = RuntimeException.class)
public void testSad() throws Exception {

    HttpServer server = HttpServer.create(new InetSocketAddress(9213), 0);
    server.createContext("/test", new MyHandler());
    server.setExecutor(null); // creates a default executor
    server.start();

    Thread.sleep(10);


    Map<String,String> headers = map("foo", "bar", "fun", "sun");

    String response = HTTP.postBodyWithContentType("http://localhost:9213/foo", headers, "text/plain", "hi mom");

    System.out.println(response);

    assertTrue(response.contains("hi mom"));
    assertTrue(response.contains("Fun=[sun], Foo=[bar]"));

    Thread.sleep(10);

    server.stop(0);


}

Puoi trovare il resto qui:

https://github.com/RichardHightower/boon

Il mio obiettivo è quello di fornire le cose comuni che si vorrebbe fare in un modo un po 'più semplice allora ....


18



Aggiornare

Il nuovo client HTTP fornito con Java 9, ma come parte di un   Modulo di incubazione denominato jdk.incubator.httpclient. I moduli dell'incubatore sono   un mezzo per mettere API non finali nelle mani degli sviluppatori mentre il   Le API avanzano verso la finalizzazione o la rimozione in un futuro   pubblicazione.

In Java 9, puoi inviare un GET richiesta come:

// GET
HttpResponse response = HttpRequest
    .create(new URI("http://www.stackoverflow.com"))
    .headers("Foo", "foovalue", "Bar", "barvalue")
    .GET()
    .response();

Quindi puoi esaminare il reso HttpResponse:

int statusCode = response.statusCode();
String responseBody = response.body(HttpResponse.asString());

Poiché questo nuovo client HTTP è in java.httpclient  jdk.incubator.httpclient modulo, dovresti dichiarare questa dipendenza nel tuo module-info.java file:

module com.foo.bar {
    requires jdk.incubator.httpclient;
}

14



Inizialmente sono stato ingannato da questo articolo che favorisce HttpClient.

Più tardi, me ne sono reso conto HttpURLConnection starà da questo articolo

Come per il blog di Google:

Il client HTTP Apache ha meno bug su Eclair e Froyo. È la scelta migliore per queste versioni. Per Gingerbread, HttpURLConnection è la scelta migliore. La sua semplice API e le ridotte dimensioni lo rendono perfetto per Android.

La compressione trasparente e la cache di risposta riducono l'utilizzo della rete, migliorano la velocità e fanno risparmiare batteria. Le nuove applicazioni dovrebbero usare HttpURLConnection; è dove andremo a spendere le nostre energie andando avanti.

Dopo aver letto Questo articolo e qualche altro stack sulle domande di flusso, ne sono convinto HttpURLConnection sta per rimanere per periodi più lunghi.

Alcune delle domande SE favorevoli HttpURLConnections:

Su Android, effettua una richiesta POST con i dati del modulo codificato URL senza utilizzare UrlEncodedFormEntity

HttpPost funziona nel progetto Java, non in Android


13



Puoi anche usare JdkRequest a partire dal jcabi-http (Sono uno sviluppatore), che fa tutto questo per te, decorando HttpURLConnection, attivando le richieste HTTP e le risposte di analisi, ad esempio:

String html = new JdkRequest("http://www.google.com").fetch().body();

Controlla questo post sul blog per maggiori informazioni: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html


10