Vraag Hoe gebruik je java.net.URLConnection om HTTP-verzoeken af ​​te vuren en af ​​te handelen


Gebruik van java.net.URLConnection wordt hier vaak gevraagd, en de Oracle zelfstudie is te beknopt over het.

Die tutorial laat eigenlijk alleen zien hoe een GET-request moet worden geactiveerd en lees het antwoord. Het legt nergens uit hoe het te gebruiken om onder andere een POST-aanvraag uit te voeren, request-headers in te stellen, antwoordheaders te lezen, cookies te verwerken, een HTML-formulier in te dienen, een bestand te uploaden, enz.

Dus, hoe kan ik gebruiken java.net.URLConnection om te schieten en "geavanceerde" HTTP-aanvragen af ​​te handelen?


1759


oorsprong


antwoorden:


Eerst een disclaimer vooraf: de geposte codefragmenten zijn allemaal basale voorbeelden. U moet triviaal afhandelen IOExceptions en RuntimeExceptions zoals NullPointerException, ArrayIndexOutOfBoundsException en vertrouwt jezelf.


voorbereidingen treffen

We moeten eerst de URL en de karakterset kennen. De parameters zijn optioneel en zijn afhankelijk van de functionele vereisten.

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

De queryparameters moeten aanwezig zijn name=value formatteren en worden samengevoegd door &. Normaal gesproken zou je dat ook doen URL-coderen de queryparameters met de opgegeven tekenset gebruiken URLEncoder#encode().

De String#format() is gewoon voor het gemak. Ik geef er de voorkeur aan als ik de String-aaneenschakelingoperator nodig heb + meer dan twee keer.


Vuren HTTP GET verzoek met (optioneel) queryparameters

Het is een triviale taak. Het is de standaard verzoekmethode.

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

Elke querystring moet worden samengevoegd aan de URL met ?. De Accept-Charset header kan de server wijzen op de codering van de parameters. Als u geen queryreeks verstuurt, kunt u de Accept-Charset header weg. Als u geen headers hoeft in te stellen, dan kunt u zelfs de URL#openStream() snelkoppeling methode.

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

Hoe dan ook, als de andere kant een is HttpServlet, dan is het doGet() methode wordt aangeroepen en de parameters zijn beschikbaar via HttpServletRequest#getParameter().

Voor testdoeleinden, kunt u de responsstructuur naar stdout afdrukken zoals hieronder:

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

Vuren HTTP POST verzoek met queryparameters

Het instellen van URLConnection#setDoOutput() naar true stelt de verzoekmethode impliciet in op POST. De standaard HTTP POST zoals webformulieren doen is van het type application/x-www-form-urlencoded waarbij de querystring is geschreven naar de aanvraagtekst.

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();
// ...

Opmerking: wanneer u een HTML-formulier programmatisch wilt indienen, vergeet dan niet het name=value paren van elk <input type="hidden"> elementen in de querystring en natuurlijk ook de name=value paar van de <input type="submit"> element dat u "programmatisch" wilt "drukken" (omdat dat meestal wordt gebruikt aan de serverzijde om te onderscheiden of er op een knop is gedrukt en zo ja, welke).

Je kunt ook de verkregen casten URLConnection naar HttpURLConnection en gebruik de HttpURLConnection#setRequestMethod() in plaats daarvan. Maar als u de verbinding voor uitvoer probeert te gebruiken, moet u deze nog instellen URLConnection#setDoOutput() naar true.

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

Hoe dan ook, als de andere kant een is HttpServlet, dan is het doPost() methode wordt aangeroepen en de parameters zijn beschikbaar via HttpServletRequest#getParameter().


Het HTTP-verzoek daadwerkelijk afvuren

U kunt het HTTP-verzoek expliciet aanvinken met URLConnection#connect(), maar het verzoek wordt automatisch op verzoek afgevuurd wanneer u informatie wilt over de HTTP-reactie, zoals het antwoordorgaan dat gebruikt URLConnection#getInputStream()enzovoort. De bovenstaande voorbeelden doen precies dat, dus de connect() bellen is eigenlijk overbodig.


Verzamelen van HTTP-antwoordinformatie

  1. HTTP-reactiestatus:

    Je hebt een nodig HttpURLConnection hier. Giet het eerst indien nodig.

    int status = httpConnection.getResponseCode();
    
  2. HTTP-antwoordheaders:

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

    Wanneer de Content-Type bevat een charset parameter, dan is de respons body waarschijnlijk op tekst gebaseerd en willen we de response body verwerken met de server-side gespecificeerde karaktercodering dan.

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

De sessie onderhouden

De sessie aan de serverzijde wordt meestal ondersteund door een cookie. Sommige webformulieren vereisen dat u bent ingelogd en / of wordt gevolgd door een sessie. U kunt de CookieHandler API om cookies te onderhouden. Je moet een bereiden CookieManager met een CookiePolicy van ACCEPT_ALL voordat alle HTTP-aanvragen worden verzonden.

// 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();
// ...

Merk op dat bekend is dat dit onder alle omstandigheden niet altijd goed werkt. Als het voor u niet lukt, kunt u het beste handmatig de cookiekoppen verzamelen en instellen. Je moet eigenlijk alles pakken Set-Cookie headers van de reactie van de login of de eerste GET aanvraag en geef dit vervolgens door aan de volgende verzoeken.

// 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]);
}
// ...

De split(";", 2)[0] is er om zich te ontdoen van cookie-attributen die niet relevant zijn voor de server-kant expires, path, enz. Als alternatief kunt u ook gebruiken cookie.substring(0, cookie.indexOf(';')) in plaats van split().


Streaming-modus

De HttpURLConnection zal standaard de buffer bufferen geheel aanvraagtekst voordat het daadwerkelijk wordt verzonden, ongeacht of u zelf een vaste lengte hebt ingesteld met connection.setRequestProperty("Content-Length", contentLength);. Dit kan leiden tot OutOfMemoryExceptions wanneer u gelijktijdig grote POST-aanvragen verzendt (bijvoorbeeld door bestanden te uploaden). Om dit te voorkomen, zou u het willen instellen HttpURLConnection#setFixedLengthStreamingMode().

httpConnection.setFixedLengthStreamingMode(contentLength);

Maar als de lengte van de inhoud eigenlijk niet van tevoren bekend is, kunt u gebruikmaken van de gesplitste streamingmodus door de HttpURLConnection#setChunkedStreamingMode() overeenkomstig. Hiermee wordt de HTTP ingesteld Transfer-Encoding header naar chunked waardoor het verzoeksysteem in brokken wordt verzonden. In het onderstaande voorbeeld wordt het lichaam in blokken van 1 KB verzonden.

httpConnection.setChunkedStreamingMode(1024);

User-Agent

Het kan gebeuren dat een verzoek retourneert een onverwacht antwoord, terwijl het prima werkt met een echte webbrowser. De serverkant blokkeert waarschijnlijk verzoeken op basis van de User-Agent verzoek header. De URLConnection zal dit standaard instellen op Java/1.6.0_19 waar het laatste deel duidelijk de JRE-versie is. U kunt dit als volgt overschrijven:

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.

Gebruik de tekenreeks User-Agent van a recente browser.


Foutafhandeling

Als de HTTP-responscode dat is 4nn (Clientfout) of 5nn (Serverfout), dan wilt u misschien de HttpURLConnection#getErrorStream() om te zien of de server nuttige foutinformatie heeft verzonden.

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

Als de HTTP-reactiecode -1 is, is er iets misgegaan met de verwerking van verbinding en reactie. De HttpURLConnection implementatie is in oudere JRE's enigszins buggy met het levend houden van verbindingen. Misschien wilt u het uitschakelen door de http.keepAlive systeemeigenschap aan false. U kunt dit programmatisch doen in het begin van uw applicatie door:

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

Bestanden uploaden

Normaal gebruik je multipart/form-data codering voor gemengde POST-inhoud (binaire en karaktergegevens). De codering wordt meer gedetailleerd beschreven 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();
}

Als de andere kant een is HttpServlet, dan is het doPost() methode wordt aangeroepen en de onderdelen zijn beschikbaar via HttpServletRequest#getPart() (let op, dus niet  getParameter() enzovoort!). De getPart() methode is echter relatief nieuw, het is geïntroduceerd in Servlet 3.0 (Glassfish 3, Tomcat 7, enz.). Voorafgaand aan Servlet 3.0 is uw beste keuze het gebruik van Apache Commons FileUpload om te ontleden multipart/form-data verzoek. Zie ook dit antwoord voor voorbeelden van zowel de benaderingen FileUpload en Servelt 3.0.


Omgaan met niet-vertrouwde of verkeerd geconfigureerde HTTPS-sites

Soms moet u een HTTPS-URL verbinden, misschien omdat u een webschraper schrijft. In dat geval kunt u waarschijnlijk een a javax.net.ssl.SSLException: Not trusted server certificate op sommige HTTPS-sites die hun SSL-certificaten niet up-to-date houden, of een java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found of javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name op sommige verkeerd geconfigureerde HTTPS-sites.

De volgende eenmalige run static initializer in uw webschraperklasse zou moeten maken HttpsURLConnection soepeler zijn met betrekking tot die HTTPS-sites en dus deze uitzonderingen niet meer weggooien.

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);
    }
}

Laatste woorden

De Apache HttpComponents HttpClient is veel handiger in dit alles :)


HTML parseren en extraheren

Als alles wat je wilt is het ontleden en extraheren van gegevens uit HTML, gebruik dan beter een HTML-parser zoals Jsoup


2525



Wanneer u met HTTP werkt, is het bijna altijd nuttiger om naar te verwijzen HttpURLConnection in plaats van de basisklasse URLConnection (sinds URLConnection is een abstracte klasse als je erom vraagt URLConnection.openConnection() op een HTTP-URL die toch terugkomt).

Dan kun je in plaats van vertrouwen op URLConnection#setDoOutput(true) om de aanvraagmethode impliciet in te stellen POST in plaats daarvan doen httpURLConnection.setRequestMethod("POST") wat sommigen misschien natuurlijker vinden (en waarmee je ook andere verzoekmethoden kunt specificeren, zoals LEGGEN, DELETE, ...).

Het biedt ook handige HTTP-constanten, zodat u het volgende kunt doen:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

84



Geïnspireerd door deze en andere vragen over SO, heb ik een minimale open source gemaakt basische HTTP-client dat de meeste van de hier gevonden technieken belichaamt.

Google-HTTP-java-client is ook een geweldige open source bron.


49



Er zijn twee opties die u kunt gebruiken bij HTTP-URL-hits: GET / POST

GET-verzoek: -

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()));

POST-aanvraag: -

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()));

22



Ik stel voor dat je de code bekijkt kevinsawicki / http-request, het is eigenlijk een verpakking bovenop HttpUrlConnection het biedt een veel eenvoudigere API voor het geval u nu gewoon de aanvragen wilt indienen of u kunt de bronnen bekijken (het is niet te groot) om te kijken hoe de verbindingen worden afgehandeld.

Voorbeeld: maak een GET verzoek met inhoudstype application/json en enkele queryparameters:

// 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);

20



Ik was ook erg geïnspireerd door dit antwoord.

Ik ben vaak op projecten waar ik wat HTTP moet doen, en ik wil misschien niet veel afhankelijkheid van derden binnenhalen (die anderen binnenhalen enzovoorts, enzovoort).

Ik ben begonnen met het schrijven van mijn eigen hulpprogramma's op basis van een deel van dit gesprek (niet waar gedaan):

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 {

Dan zijn er slechts een aantal of statische methoden.

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

Post dan ...

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

Nou, je snapt het idee ....

Dit zijn de tests:

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


}

Je kunt de rest hier vinden:

https://github.com/RichardHightower/boon

Mijn doel is om de gemeenschappelijke dingen die je zou willen doen op een iets eenvoudiger manier aan te bieden dan ....


19



Bijwerken

De nieuwe HTTP-client is geleverd met Java 9, maar als onderdeel van een   Incubator-module genoemd jdk.incubator.httpclient. Incubator-modules zijn   een manier om niet-definitieve API's in handen te houden van ontwikkelaars, terwijl de   API's gaan in de toekomst over naar de afronding of verwijdering   vrijlating.

In Java 9 kunt u een verzenden GET verzoek als:

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

Dan kunt u de geretourneerde onderzoeken HttpResponse:

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

Omdat deze nieuwe HTTP-client is geïnstalleerd java.httpclient  jdk.incubator.httpclient module, moet u deze afhankelijkheid in uw declareren module-info.java het dossier:

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

15



Aanvankelijk werd ik hierdoor misleid artikel wat goed is HttpClient.

Later heb ik me dat gerealiseerd HttpURLConnection zal hier vanaf blijven artikel

Volgens het Google-blog:

Apache HTTP-client heeft minder fouten op Eclair en Froyo. Het is de beste keuze voor deze releases. Voor Gingerbread is HttpURLConnection de beste keuze. De eenvoudige API en het kleine formaat maken het geschikt voor Android.

Transparante compressie en responscaching verminderen het netwerkgebruik, verbeteren de snelheid en besparen de batterij. Nieuwe applicaties moeten HttpURLConnection gebruiken; het is waar we onze energie in de toekomst gaan besteden.

Na het lezen Dit artikel en nog wat andere vragen over stack-flow, ik ben ervan overtuigd dat HttpURLConnection blijft langer aanwezig.

Sommige van de SE-vragen zijn favoriet HttpURLConnections:

Maak op Android een POST-aanvraag met URL-gecodeerde formuliergegevens zonder UrlEncodedFormEntity te gebruiken

HttpPost werkt in een Java-project, niet in Android


14



Je kan ook gebruiken JdkRequest van jcabi-http (Ik ben een ontwikkelaar), die al dit werk voor je doet, HttpURLConnection versiert, HTTP-verzoeken afvuurt en antwoorden analyseert, bijvoorbeeld:

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

Bekijk deze blogpost voor meer info: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html


11



Er is ook OkHttp, een HTTP-client die standaard efficiënt is:

  • Met HTTP / 2-ondersteuning kunnen alle verzoeken aan dezelfde host een socket delen.
  • Verbindingspooling vermindert de wachttijd van de aanvraag (als HTTP / 2 niet beschikbaar is).
  • Transparante GZIP verkleint de downloadgroottes.
  • Response caching vermijdt het netwerk volledig voor herhaalverzoeken.

Maak eerst een instantie van OkHttpClient:

OkHttpClient client = new OkHttpClient();

Bereid je dan voor GET verzoek:

Request request = new Request.Builder()
      .url(url)
      .build();

gebruik ten slotte OkHttpClient om voorbereid te verzenden Request:

Response response = client.newCall(request).execute();

Voor meer informatie, kunt u de OkHttp's documentatie


11



als u http get gebruikt, verwijder dan deze regel

urlConnection.setDoOutput(true);

10