stackoverflow Wie man mit java.net.URLConnection HTTP-Anfragen auslöst und verarbeitet




java httpurlconnection post (10)

Die Verwendung von java.net.URLConnection wird hier ziemlich oft gefragt, und das Oracle-Tutorial ist zu kurz gefasst.

Dieses Tutorial zeigt im Grunde nur, wie man eine GET-Anfrage auslöst und die Antwort liest. Es wird nirgends erklärt, wie man es unter anderem zum Ausführen einer POST-Anfrage, zum Setzen von Anforderungsheadern, zum Lesen von Antwortheadern, zum Umgang mit Cookies, zum Senden eines HTML-Formulars, zum Hochladen einer Datei usw. verwendet.

Also, wie kann ich java.net.URLConnection , um "erweiterte" HTTP-Anfragen java.net.URLConnection und zu behandeln?


Diese Antwort hat mich sehr inspiriert.

Ich bin oft auf Projekten, wo ich etwas HTTP tun muss, und ich möchte vielleicht nicht viele Abhängigkeiten von Drittanbietern einbringen (die andere hereinbringen und so weiter, usw.)

Ich fing an, meine eigenen Dienstprogramme zu schreiben, basierend auf einigen dieser Konversation (nicht wo getan):

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 {

Dann gibt es nur eine Reihe oder 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;
    }
}

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

Nun, Sie bekommen die Idee ....

Hier sind die 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);


}

Den Rest finden Sie hier:

https://github.com/RichardHightower/boon

Mein Ziel ist es, die allgemeinen Dinge, die man tun möchte, etwas einfacher zu machen als ...


Ich schlage vor, Sie schauen sich den Code auf kevinsawicki/http-request , es ist im Grunde ein Wrapper oben auf HttpUrlConnection es bietet eine viel einfachere API für den Fall, dass Sie nur die Anfragen gerade jetzt machen wollen, oder Sie können einen Blick auf die Quellen (es ist nicht zu groß), um zu sehen, wie Verbindungen gehandhabt werden.

Beispiel: Erstellen Sie eine GET Anfrage mit dem Inhaltstyp application/json und einigen Abfrageparametern:

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

if you are using http get please remove this line

urlConnection.setDoOutput(true);

I recomend http-request built on apache http api. (I'm a developer)

Perform HTTP GET request

static final HttpRequest<String> httpRequest =
     HttpRequestBuilder.createGet(someUri, String.class)
     .responseDeserializer(ResponseDeserializer.ignorableDeserializer()).build();

ResponseHandler<String> responseHandler = httpRequest.execute(requestParameters);

int statusCode = responseHandler.getStatusCode();
String responseBody = responseHandler.get(); // see javadoc of get method

oder

 ResponseHandler<String> responseHandler = 
      httpRequest.executeWithQuery(queryString); //queryString example "param1=param1&param2=param2"

Perform HTTP POST request

Replace HttpRequestBuilder.createGet to HttpRequestBuilder.createPost

Add headers

static final HttpRequest<String> httpRequest =
      HttpRequestBuilder.createGet(someUri, String.class)
           .responseDeserializer(ResponseDeserializer.ignorableDeserializer())
           .addDefaultHeader("Accept", "application/json")
           .build();

Convert response to type

let's say response is JSON and you know it

{"name":"myname","lastname":"mylastname","age":25}

You must create class User:

public User{
    private String Name;
    private String Lastname;
    private int Age;

   // getters and setters
}

static final HttpRequest<User> httpRequest =
     HttpRequestBuilder.createGet(someUri, User.class).build();

ResponseHandler<User> responseHandler = httpRequest.execute(requestParameters);
User userFromResponse = responseHandler.orElse(null); //returns null if content isn't present
System.out.print(user.getName()); //myname

Note: You don't need to worry about Exceptions. All exceptions is wrapped.


Zuerst ein Haftungsausschluss: Die eingeblendeten Code-Snippets sind alles Beispiele. Sie müssen triviale IOException s und RuntimeException wie NullPointerException , ArrayIndexOutOfBoundsException und ArrayIndexOutOfBoundsException selbst behandeln.

Vorbereitung

Wir müssen zuerst mindestens die URL und den Zeichensatz kennen. Die Parameter sind optional und hängen von den funktionalen Anforderungen ab.

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

Die Abfrageparameter müssen im Format name=value und von & verkettet werden. Normalerweise würden Sie die Abfrageparameter auch mit dem angegebenen Zeichensatz URL-encode indem Sie URLEncoder#encode() .

Das String#format() dient nur der Bequemlichkeit. Ich bevorzuge es, wenn ich den String-Verkettungsoperator + mehr als zweimal benötigen würde.

Absetzen einer HTTP GET- Anfrage mit (optional) Abfrageparametern

Es ist eine triviale Aufgabe. Es ist die Standardanforderungsmethode.

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

Jede Abfragezeichenfolge sollte mit der URL verkettet werden, indem ? . Der Accept-Charset Header kann den Server darauf Accept-Charset welche Kodierung die Parameter enthalten. Wenn Sie keine Abfragezeichenfolge senden, können Sie die Accept-Charset Kopfzeile Accept-Charset . Wenn Sie keine Header festlegen müssen, können Sie sogar die Verknüpfungsmethode URL#openStream() verwenden.

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

In jedem Fall wird, wenn die andere Seite ein HttpServlet , die doGet() -Methode aufgerufen und die Parameter werden von HttpServletRequest#getParameter() .

Zu Testzwecken können Sie den Antworttext wie folgt ausdrucken:

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

Absetzen einer HTTP-POST- Anfrage mit Abfrageparametern

Wenn Sie URLConnection#setDoOutput() auf true setzen, wird die Anforderungsmethode implizit auf POST gesetzt. Der Standard-HTTP-POST als Webformulare hat den Typ application/x-www-form-urlencoded wobei die application/x-www-form-urlencoded in den application/x-www-form-urlencoded geschrieben wird.

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

Hinweis: Wenn Sie ein HTML-Formular programmatisch übermitteln möchten, vergessen Sie nicht, die name=value Paare beliebiger <input type="hidden"> -Elemente in die Abfragezeichenfolge aufzunehmen und natürlich auch das name=value Paar von das <input type="submit"> -Element, das Sie programmgesteuert "drücken" möchten (weil das normalerweise auf der Serverseite verwendet wird, um zu unterscheiden, ob eine Schaltfläche gedrückt wurde und wenn ja, welche).

Sie können die erlangte java.net.URLConnection auf HttpURLConnection und stattdessen HttpURLConnection#setRequestMethod() verwenden. Wenn Sie jedoch versuchen, die Verbindung für die Ausgabe zu verwenden, müssen Sie URLConnection#setDoOutput() auf true .

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

In jedem Fall wird, wenn die andere Seite ein HttpServlet , die Methode doPost() aufgerufen und die Parameter werden von HttpServletRequest#getParameter() .

Tatsächlich feuern die HTTP-Anfrage

Sie können die HTTP-Anforderung explizit mit URLConnection#connect() , die Anforderung wird jedoch bei Bedarf automatisch ausgelöst, wenn Sie Informationen zur HTTP-Antwort erhalten möchten, z. B. den Antworttext mit URLConnection#getInputStream() . Die obigen Beispiele machen genau das, daher ist der Aufruf connect() tatsächlich überflüssig.

Sammeln von HTTP-Antwortinformationen

  1. HTTP-Antwortstatus :

    Sie benötigen hier eine HttpURLConnection . Wirf es zuerst, wenn es nötig ist.

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

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

    Wenn der Content-Type einen charset enthält, ist der Antworttext wahrscheinlich textbasiert, und wir möchten den Antworttext dann mit der serverseitig angegebenen Zeichenkodierung verarbeiten.

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

Aufrechterhaltung der Sitzung

Die serverseitige Sitzung wird normalerweise von einem Cookie unterstützt. Bei einigen Webformularen müssen Sie angemeldet und / oder von einer Sitzung überwacht werden. Sie können die CookieHandler API verwenden, um Cookies zu verwalten. Sie müssen einen CookieManager mit einer CookiePolicy von ACCEPT_ALL bevor Sie alle HTTP-Anfragen senden.

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

Beachten Sie, dass dies unter allen Umständen nicht immer ordnungsgemäß funktioniert. Wenn es für Sie fehlschlägt, ist es am besten, die Cookie-Header manuell zu sammeln und festzulegen. Sie müssen im Grunde alle Set-Cookie Header von der Antwort des Logins oder der ersten GET Anfrage übernehmen und diese dann durch die nachfolgenden Anfragen weiterleiten.

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

Die split(";", 2)[0] ist da, um Cookie-Attribute loszuwerden, die für die Serverseite irrelevant sind, wie expires , path , etc. Alternativ können Sie auch cookie.substring(0, cookie.indexOf(';')) statt split() .

Streaming-Modus

Die HttpURLConnection standardmäßig den gesamten HttpURLConnection bevor sie tatsächlich HttpURLConnection wird, unabhängig davon, ob Sie selbst eine feste Inhaltslänge mit connection.setRequestProperty("Content-Length", contentLength); . Dies kann OutOfMemoryException s verursachen, wenn Sie gleichzeitig große POST-Anfragen senden (zB Hochladen von Dateien). Um dies zu vermeiden, möchten Sie die HttpURLConnection#setFixedLengthStreamingMode() .

httpConnection.setFixedLengthStreamingMode(contentLength);

Wenn die Länge des Inhalts jedoch vorher nicht bekannt ist, können Sie den HttpURLConnection#setChunkedStreamingMode() Streaming-Modus verwenden, indem Sie HttpURLConnection#setChunkedStreamingMode() entsprechend HttpURLConnection#setChunkedStreamingMode() . Dadurch wird der HTTP- Transfer-Encoding Header auf chunked wodurch der gesendete Request-Body in Chunks chunked wird. Das folgende Beispiel sendet den Körper in Blöcken von 1 KB.

httpConnection.setChunkedStreamingMode(1024);

User-Agent

Es kann vorkommen, dass eine Anfrage eine unerwartete Antwort zurückgibt, während sie mit einem echten Webbrowser funktioniert. Die Serverseite blockiert wahrscheinlich Anfragen basierend auf dem User-Agent Anfrage-Header. Die URLConnection wird standardmäßig auf Java/1.6.0_19 wobei der letzte Teil offensichtlich die JRE-Version ist. Sie können dies wie folgt überschreiben:

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.

Verwenden Sie die User-Agent-Zeichenfolge aus einem aktuellen Browser .

Fehlerbehandlung

Wenn der HTTP-Antwortcode 4nn (Client Error) oder 5nn (Server Error) 5nn , sollten Sie die HttpURLConnection#getErrorStream() lesen, um HttpURLConnection#getErrorStream() , ob der Server nützliche Informationen gesendet hat.

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

Wenn der HTTP-Antwortcode -1 ist, ist bei der Verarbeitung der Verbindung und der Antwort ein Fehler aufgetreten. Die HttpURLConnection Implementierung ist in älteren JREs etwas fehlerhaft und hält Verbindungen aufrecht. Möglicherweise möchten Sie es http.keepAlive , indem Sie die http.keepAlive Systemeigenschaft auf false http.keepAlive . Sie können dies programmatisch am Anfang Ihrer Anwendung tun, indem Sie:

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

Hochladen von Dateien

Normalerweise würden Sie multipart/form-data für gemischten POST-Inhalt (Binär- und Zeichendaten) verwenden. Die Codierung wird im Detail 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();
}

Wenn die andere Seite ein HttpServlet , dann wird ihre Methode doPost() aufgerufen und die Teile werden durch HttpServletRequest#getPart() verfügbar sein (beachte, getParameter() usw. nicht!). Die Methode getPart() ist jedoch relativ neu, sie wurde in Servlet 3.0 eingeführt (Glassfish 3, Tomcat 7, usw.). Vor Servlet 3.0 verwenden Sie am besten Apache Commons FileUpload , um eine multipart/form-data zu analysieren. Siehe auch diese Antwort für Beispiele der FileUpload- und der Servelt 3.0-Ansätze.

Umgang mit nicht vertrauenswürdigen oder falsch konfigurierten HTTPS-Sites

Manchmal müssen Sie eine HTTPS-URL verbinden, vielleicht weil Sie einen Web-Scraper schreiben. In diesem Fall können Sie sich wahrscheinlich einer javax.net.ssl.SSLException: Not trusted server certificate auf einigen HTTPS-Sites, die ihre SSL-Zertifikate nicht auf dem neuesten Stand halten, oder eine java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found oder javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name auf einigen falsch konfigurierten HTTPS-Sites.

Der folgende einmalig laufende static Initialisierer in Ihrer Web- HttpsURLConnection Klasse sollte HttpsURLConnection gegenüber diesen HTTPS-Sites milder machen und diese Ausnahmen daher nicht mehr HttpsURLConnection .

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

Letzte Worte

Der Apache HttpComponents HttpClient ist viel bequemer in diesem alles :)

Parsen und Extrahieren von HTML

Wenn Sie nur Daten aus HTML analysieren und extrahieren möchten, verwenden Sie besser einen HTML-Parser wie Jsoup


Aktualisieren

Der neue HTTP-Client wurde mit Java 9 ausgeliefert, jedoch als Teil eines Incubator-Moduls namens jdk.incubator.httpclient . Incubator-Module sind ein Mittel, um nicht endgültige APIs in die Hände von Entwicklern zu geben, während die APIs in einer zukünftigen Version entweder finalisiert oder entfernt werden.

In Java 9 können Sie eine GET Anfrage senden wie:

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

Dann können Sie die zurückgegebene HttpResponse :

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

Da dieser neue HTTP-Client in ist java.httpclient jdk.incubator.httpclient Modul, sollten Sie diese Abhängigkeit in Ihrer module-info.java Datei module-info.java :

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

Es gibt 2 Optionen, die Sie mit HTTP-URL-Hits aufrufen können: GET / POST

GET Anfrage: -

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

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

Bei der Arbeit mit HTTP ist es fast immer sinnvoller, auf HttpURLConnection anstatt auf die Basisklasse URLConnection zu verweisen (da URLConnection eine abstrakte Klasse ist, wenn Sie URLConnection.openConnection() nach einer HTTP-URL fragen, die Sie sowieso erhalten).

Dann können Sie statt auf URLConnection#setDoOutput(true) setzen, um die Request-Methode implizit auf POST zu setzen, stattdessen httpURLConnection.setRequestMethod("POST") was einige natürlicher finden könnten (und die Ihnen auch erlaubt, andere Anfrage-Methoden wie PUT , DELETE , ...).

Es bietet auch nützliche HTTP-Konstanten, so dass Sie Folgendes tun können:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

Inspiriert von dieser und anderen Fragen zu SO habe ich einen minimalen Open-Source- basic-http-client , der die meisten der hier gefundenen Techniken enthält.

google-http-java-client ist auch eine große Open-Source-Ressource.


Anfangs wurde ich von diesem article der HttpClient favorisiert, in die Irre geführt.

Später wurde mir klar, dass HttpURLConnection von diesem article HttpURLConnection bleiben wird

Wie im Google Blog :

Apache HTTP-Client hat weniger Fehler bei Eclair und Froyo. Es ist die beste Wahl für diese Veröffentlichungen. Für Lebkuchen ist HttpURLConnection die beste Wahl. Seine einfache API und geringe Größe macht es ideal für Android.

Transparentes Komprimierungs- und Antwort-Caching reduziert den Netzwerkverbrauch, verbessert die Geschwindigkeit und spart Batterie. Neue Anwendungen sollten HttpURLConnection verwenden; Hier werden wir unsere Energie für die Zukunft einsetzen.

Nach dem Lesen rapidvaluesolutions.com/tech_blog/… und einigen anderen Stack-über-Flow-Fragen bin ich überzeugt, dass HttpURLConnection länger bleiben wird.

Einige der SE-Fragen begünstigen HttpURLConnections :

Nehmen Sie unter Android eine POST-Anfrage mit URL-codierten Formulardaten vor, ohne UrlEncodedFormEntity zu verwenden

HttpPost funktioniert in Java-Projekt, nicht in Android





urlconnection