Jak używać java.net.URLConnection do odpalania i obsługi żądań HTTP?

Użycie java.net.URLConnection jest tu dość często zadawane pytania, a samouczek Oracle jest zbyt zwięzły.

Ten samouczek pokazuje tylko, jak odpalić żądanie GET I Odczytać odpowiedź. Nigdzie nie wyjaśnia, jak go używać między innymi do wykonywania żądania POST, ustawiania nagłówków żądań, odczytu nagłówków odpowiedzi, radzenia sobie z ciasteczkami, przesyłania formularza HTML, przesyłania pliku itp.

Więc jak mogę użyć java.net.URLConnection do odpalenia i obsługi " Zaawansowanego" Żądania HTTP?

Author: BalusC, 2010-05-08

11 answers

najpierw zastrzeżenie: opublikowane fragmenty kodu są podstawowymi przykładami. Będziesz musiał obsługiwać trywialne IOExceptions I RuntimeException s jak NullPointerException, ArrayIndexOutOfBoundsException i małżonki siebie.


Przygotowanie

Najpierw musimy znać przynajmniej adres URL i kodowanie. Parametry są opcjonalne i zależą od wymagań funkcjonalnych.

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

Parametry zapytania muszą być w formacie name=value i muszą być połączone przez &. Normalnie też byś URL-encode parametry zapytania z podanym zestawem znaków za pomocą URLEncoder#encode().

String#format() jest tylko dla wygody. Wolę, gdy operator konkatenacji + jest potrzebny więcej niż dwa razy.


Wywołanie zapytania HTTP GET z (opcjonalnie) parametrami zapytania

To trywialne zadanie. Jest to domyślna metoda żądania.
URLConnection connection = new URL(url + "?" + query).openConnection();
connection.setRequestProperty("Accept-Charset", charset);
InputStream response = connection.getInputStream();
// ...

Każdy łańcuch zapytania powinien być połączony z adresem URL za pomocą ?. Na Accept-Charset nagłówek może podpowiedzieć serwerowi, w jakim kodowaniu są parametry. Jeśli nie wyślesz żadnego ciągu zapytania, możesz zostawić nagłówek Accept-Charset. Jeśli nie musisz ustawiać żadnych nagłówków, możesz nawet użyć URL#openStream() metoda skrótu.

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

Tak czy inaczej, jeśli druga strona jest HttpServlet, wtedy jego doGet() metoda zostanie wywołana, a parametry będą dostępne przez HttpServletRequest#getParameter().

W celach testowych, ty może wydrukować treść odpowiedzi na stdout jak poniżej:

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

Wywołanie zapytania HTTP POST z parametrami zapytania

Ustawianie URLConnection#setDoOutput() to true domyślnie ustawia metodę żądania na POST. Standardowy POST HTTP jako web forms jest typu application/x-www-form-urlencoded, w którym łańcuch zapytania jest zapisywany do ciała żądania.

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

Uwaga: Gdy chcesz programowo przesłać formularz HTML, nie zapomnij wziąć name=value par dowolnych <input type="hidden"> elementów do łańcucha zapytania i oczywiście również name=value pary <input type="submit"> elementu, który chciałbyś "nacisnąć" programowo(ponieważ zwykle jest to używane po stronie serwera, aby odróżnić, czy przycisk został naciśnięty, a jeśli tak, to który).

Można również rzucić uzyskane URLConnection na HttpURLConnection i korzystać z jego HttpURLConnection#setRequestMethod() zamiast tego. Ale jeśli próbujesz użyć połączenia do wyjścia, nadal musisz ustawić URLConnection#setDoOutput() na true.

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

Tak czy inaczej, jeśli druga strona jest HttpServlet, wtedy jego doPost() metoda zostanie wywołana, a parametry będą dostępne przez HttpServletRequest#getParameter().


Uruchamianie żądania HTTP

Można odpalić żądanie HTTP jawnie za pomocą URLConnection#connect(), ale żądanie zostanie automatycznie wywołane na żądanie, gdy chcesz uzyskać jakiekolwiek informacje o odpowiedzi HTTP, takie jak ciało odpowiedzi za pomocą URLConnection#getInputStream() i tak dalej. Powyższe przykłady robią dokładnie to, więc wywołanie connect() jest w rzeczywistości zbędne.


Zbieranie informacji o odpowiedzi HTTP

  1. status odpowiedzi HTTP :

Potrzebujesz HttpURLConnection proszę. Rzuć ją najpierw, jeśli to konieczne.

    int status = httpConnection.getResponseCode();
  1. Nagłówki odpowiedzi HTTP :

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

Gdy Content-Type zawiera parametr charset, wtedy ciało odpowiedzi jest prawdopodobnie oparte na tekście i chcielibyśmy przetworzyć ciało odpowiedzi z określonym kodowaniem znaków po stronie serwera.

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

Utrzymanie sesji

Sesja po stronie serwera jest zwykle wspierana przez plik cookie. Niektóre formularze internetowe wymagają zalogowania się i / lub śledzenia przez sesję. Możesz użyć CookieHandler API do obsługi plików cookie. Musisz przygotować CookieManager z CookiePolicy z ACCEPT_ALL przed wysłaniem wszystkich żądań 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();
// ...

Zauważ, że wiadomo, że nie zawsze działa prawidłowo w każdych okolicznościach. Jeśli ci się nie powiedzie, najlepiej ręcznie zebrać i ustawić nagłówki plików cookie. Zasadniczo musisz pobrać wszystkie nagłówki Set-Cookie Z odpowiedzi logowania lub pierwszego żądania GET, a następnie przekazać je przez kolejne żądania.

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

split(";", 2)[0] jest po to, aby pozbyć się atrybutów ciasteczek, które są nieistotne dla strony serwera jak expires, path, itd. Alternatywnie można również użyć cookie.substring(0, cookie.indexOf(';')) zamiast split().


Streaming mode

The HttpURLConnection domyślnie bufor całego ciała żądania przed wysłaniem go, niezależnie od tego, czy sam Ustawiłeś stałą długość zawartości za pomocą connection.setRequestProperty("Content-Length", contentLength);. Może to spowodować OutOfMemoryExceptionS za każdym razem, gdy jednocześnie wysyłasz Duże żądania postów (np. przesyłanie plików). Aby tego uniknąć, chcesz ustawić HttpURLConnection#setFixedLengthStreamingMode().

httpConnection.setFixedLengthStreamingMode(contentLength);

Ale jeśli długość zawartości naprawdę nie jest wcześniej znana, możesz skorzystać z trybu strumieniowego chunked, ustawiając HttpURLConnection#setChunkedStreamingMode() odpowiednio. To ustawi HTTP Transfer-Encoding nagłówek do chunked, który wymusi wysłanie ciała żądania w kawałkach. Poniższy przykład wyśle ciało w kawałkach 1KB.

httpConnection.setChunkedStreamingMode(1024);

User-Agent

Może się zdarzyć, że żądanie zwróci nieoczekiwaną odpowiedź, podczas gdy działa dobrze z prawdziwą przeglądarką internetową . Strona serwera prawdopodobnie blokuje żądania w oparciu o User-Agent nagłówek żądania. URLConnection domyślnie ustawia ją na Java/1.6.0_19, gdzie ostatnia część jest oczywiście wersją JRE. Można to zastąpić w następujący sposób:

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.

Użyj ciągu User-Agent z ostatniej przeglądarki .


Obsługa błędów

Jeśli kod odpowiedzi HTTP to 4nn (błąd Klienta) lub 5nn (błąd serwera), możesz chcieć przeczytaj HttpURLConnection#getErrorStream(), aby sprawdzić, czy serwer wysłał jakieś przydatne informacje o błędach.

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

Jeśli kod odpowiedzi HTTP wynosi -1, to coś poszło nie tak z obsługą połączenia i odpowiedzi. Implementacja HttpURLConnection jest w starszych wersjach JRE nieco błędna, co pozwala utrzymać połączenia przy życiu. Można ją wyłączyć, ustawiając właściwość systemową http.keepAlive na false. Można to zrobić programowo na początku aplikacji przez:

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

Wgrywanie plików

You ' d normalnie używać multipart/form-data kodowanie dla mieszanej zawartości posta(dane binarne i znakowe). Kodowanie jest bardziej szczegółowo opisane w 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();
}

Jeśli druga strona jest HttpServlet, wtedy jego doPost() metoda zostanie wywołana, a części będą dostępne przez HttpServletRequest#getPart() (Uwaga, zatem nie getParameter() i tak dalej!). Metoda getPart() jest jednak stosunkowo nowa, została wprowadzona w Servlet 3.0 (Glassfish 3, Tomcat 7, itd.). Prior do Servleta 3.0 najlepiej jest użyć Apache Commons FileUpload do przetworzenia multipart/form-data żądania. Zobacz również ta odpowiedź dla przykładowych podejść FileUpload i Servelt 3.0.


W związku z tym, że nie jest to możliwe, nie jest to możliwe.]}

Czasami musisz podłączyć adres URL HTTPS, być może dlatego, że piszesz skrobak internetowy. W takim przypadku prawdopodobnie możesz napotkać javax.net.ssl.SSLException: Not trusted server certificate na niektórych witrynach HTTPS, którzy nie utrzymują swoich certyfikatów SSL do Data, lub java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found lub javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name na niektórych źle skonfigurowanych witrynach HTTPS.

Następująca Jednorazowa inicjalizacja static w twojej klasie skrobaka internetowego powinna sprawić, że HttpsURLConnection będzie bardziej łagodna w stosunku do tych witryn HTTPS, a tym samym nie będzie już wyrzucać tych wyjątków.

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

Ostatnie słowa

The Apache HttpComponents HttpClient is much more convenient in this all:)


Parsowanie i wyodrębnianie HTML

Jeśli chcesz tylko parsować i wydobywać dane z HTML, lepiej Użyj parsera HTML, takiego jak Jsoup

 2739
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-06 13:27:02

Podczas pracy z HTTP prawie zawsze bardziej przydatne jest odwoływanie się do HttpURLConnection, a nie do klasy bazowej URLConnection (ponieważ URLConnection jest klasą abstrakcyjną, gdy poprosisz o URLConnection.openConnection() na URL HTTP, to i tak dostaniesz z powrotem).

Wtedy możesz zamiast polegać na URLConnection#setDoOutput(true) domyślnie ustawić metodę żądania na POST zamiast tego zrobić httpURLConnection.setRequestMethod("POST"), która może być bardziej naturalna (i która pozwala również określić inne metody żądania, takie jak PUT, DELETE , ...).

Dostarcza również użyteczne stałe HTTP, dzięki czemu można to zrobić:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {
 93
Author: Paal Thorstensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-17 00:24:55

Zainspirowany tym i innymi pytaniami na SO, stworzyłem minimalny open source basic-http-client , który ucieleśnia większość technik znalezionych tutaj.

Google-http-java-client jest również świetnym zasobem open source.

 54
Author: David Chandler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-13 16:37:47

Proponuję rzucić okiem na kod na kevinsawicki/http-request , jest to w zasadzie wrapper na górze HttpUrlConnection zapewnia znacznie prostsze API w przypadku, gdy chcesz tylko złożyć żądania teraz lub możesz spojrzeć na źródła (nie jest zbyt duże), aby spojrzeć na to, jak połączenia są obsługiwane.

Przykład: Wyślij zapytanie GET z typem zawartości application/json i niektórymi parametrami zapytania:

// 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);
 26
Author: fernandohur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-24 13:43:51

Update

Nowy klient HTTP dostarczony z Javą 9, ale jako część Moduł inkubatora o nazwie jdk.incubator.httpclient. Moduły inkubatora to sposób oddania niekończących się API w ręce programistów, podczas gdy Postępy w kierunku finalizacji lub usunięcia interfejsów API w przyszłości uwolnij.

W Javie 9 możesz wysłać GET zapytanie typu:

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

Następnie możesz sprawdzić zwrócony HttpResponse:

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

Ponieważ ten nowy klient HTTP jest w java.httpclient jdk.incubator.httpclient moduł, powinieneś zadeklarować tę zależność w swoim pliku module-info.java:

module com.foo.bar {
    requires jdk.incubator.httpclient;
}
 25
Author: Ali Dehghani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-30 15:16:39

Istnieją 2 opcje, które możesz wybrać z http URL Hits: GET / POST

GET Request: -

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

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()));
 24
Author: Utkash Bhatt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-05 16:40:31

Zainspirowała mnie również ta odpowiedź.

Często jestem w projektach, w których muszę wykonać jakiś HTTP, i mogę nie chcieć wprowadzać wielu zależności od stron trzecich (które wprowadzają inne itd. itd.).)

Zacząłem pisać własne narzędzia na podstawie niektórych z tej rozmowy (nie gdzie zrobione):

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 {

Wtedy jest tylko kilka metod statycznych.

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

Następnie post...

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

Oto testy:

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


}

Resztę znajdziesz tutaj:

Https://github.com/RichardHightower/boon

Moim celem jest zapewnienie wspólnych rzeczy, które chcieliby zrobić w nieco łatwiejszy sposób....

 23
Author: RickHigh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-17 05:35:17

Początkowo zostałem wprowadzony w błąd przez ten Artykuł , który faworyzuje HttpClient.

Później zdałem sobie sprawę, że HttpURLConnection pozostanie z tego artykułu

Jak na blogu Google :

Klient HTTP Apache ma mniej błędów na Eclair i Froyo. Jest to najlepszy wybór dla tych wydawnictw. W przypadku Piernika najlepszym wyborem jest HttpURLConnection. Jego prosty API i mały rozmiar sprawiają, że świetnie pasuje do Androida.

Przezroczysta kompresja i odpowiedź buforowanie zmniejsz zużycie sieci, popraw prędkość i oszczędzaj baterię. Nowe aplikacje powinny korzystać z HttpURLConnection; to tam będziemy wydawać naszą energię w przyszłości.

Po przeczytaniu tego artykułu i kilku innych pytań stack over flow, jestem przekonany, że HttpURLConnection zostanie na dłużej.

Niektóre z pytań SE HttpURLConnections:

Na Androidzie wykonaj żądanie POST z zakodowanym adresem URL danych formularza bez użycia UrlEncodedFormEntity

HttpPost działa w projekcie Java, a nie w Androidzie

 18
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Istnieje również OkHttp , który jest klientem HTTP, który jest domyślnie wydajny:

  • obsługa HTTP / 2 pozwala wszystkim żądaniom do tego samego hosta na współdzielenie gniazda.
  • łączenie połączeń zmniejsza opóźnienie żądania (jeśli HTTP/2 nie jest dostępny).
  • przezroczysty GZIP zmniejsza rozmiary pobierania.
  • buforowanie odpowiedzi unika sieci CAŁKOWICIE dla powtarzających się żądań.

Najpierw Utwórz instancję OkHttpClient:

OkHttpClient client = new OkHttpClient();

Następnie przygotuj swoją GET prośbę:

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

Na koniec użyj OkHttpClient Aby wysłać przygotowany Request:

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

Aby uzyskać więcej informacji, zapoznaj się z dokumentacją OkHttp

 16
Author: Ali Dehghani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-15 12:06:33

Możesz również użyć JdkRequest z jcabi-http (jestem programistą), który robi to wszystko za Ciebie, dekorując HttpURLConnection, uruchamiając żądania HTTP i analizując odpowiedzi, na przykład:

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

Sprawdź ten wpis na blogu, aby uzyskać więcej informacji: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html

 15
Author: yegor256,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-11 18:54:16

Jeśli używasz HTTP get usuń ten wiersz

urlConnection.setDoOutput(true);
 13
Author: Nison Cheruvathur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 07:15:18