Pertanyaan Cara menggunakan java.net.URLConnection untuk memecat dan menangani permintaan HTTP


Penggunaan java.net.URLConnection ditanya tentang cukup sering di sini, dan Tutorial Oracle aku s terlalu ringkas tentang itu.

Tutorial itu pada dasarnya hanya menunjukkan cara mengaktifkan permintaan GET dan membaca tanggapannya. Tidak dijelaskan di mana pun cara menggunakannya untuk antara lain melakukan permintaan POST, mengatur tajuk permintaan, membaca header tanggapan, menangani cookie, mengirimkan formulir HTML, mengunggah file, dll.

Jadi, bagaimana saya bisa menggunakannya java.net.URLConnection memecat dan menangani permintaan HTTP "lanjutan"?


1759


asal


Jawaban:


Pertama, penafian sebelumnya: cuplikan kode yang diposting adalah semua contoh dasar. Anda harus menangani hal-hal sepele IOExceptions dan RuntimeExceptionseperti NullPointerException, ArrayIndexOutOfBoundsException dan permaisuri sendiri.


Mempersiapkan

Pertama-tama kita perlu mengetahui setidaknya URL dan charset. Parameter bersifat opsional dan bergantung pada persyaratan fungsional.

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

Parameter kueri harus dalam name=value format dan disatukan oleh &. Anda biasanya juga URL-encode parameter query dengan menggunakan charset yang ditentukan URLEncoder#encode().

Itu String#format() hanya untuk kenyamanan. Saya lebih suka ketika saya akan membutuhkan operator Rangkaian String + lebih dari dua kali.


Menembakkan a HTTP GET permintaan dengan parameter kueri (opsional)

Ini tugas yang sepele. Ini adalah metode permintaan default.

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

Setiap string kueri harus digabung ke URL menggunakan ?. Itu Accept-Charset header mungkin mengisyaratkan server apa yang menyandikan parameter. Jika Anda tidak mengirim string kueri, maka Anda dapat meninggalkan Accept-Charset menjauh. Jika Anda tidak perlu mengatur header, maka Anda bahkan dapat menggunakan URL#openStream() metode pintas.

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

Bagaimanapun, jika sisi lain adalah a HttpServlet, lalu itu doGet() metode akan dipanggil dan parameter akan tersedia oleh HttpServletRequest#getParameter().

Untuk tujuan pengujian, Anda dapat mencetak tubuh respons ke stdout seperti di bawah ini:

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

Menembakkan a HTTP POST permintaan dengan parameter kueri

Pengaturan URLConnection#setDoOutput() untuk true secara implisit menetapkan metode permintaan ke POST. HTTP POST standar sebagai formulir web adalah tipe application/x-www-form-urlencoded dimana string kueri ditulis ke badan permintaan.

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

Catatan: setiap kali Anda ingin mengirimkan formulir HTML secara terprogram, jangan lupa untuk mengambil name=value pasang apa saja <input type="hidden"> elemen ke dalam string query dan tentu saja juga name=value sepasang dari <input type="submit"> elemen yang Anda ingin "tekan" secara terprogram (karena itu biasanya telah digunakan di sisi server untuk membedakan jika tombol ditekan dan jika demikian, yang mana).

Anda juga bisa membuang yang diperoleh URLConnection untuk HttpURLConnection dan gunakan itu HttpURLConnection#setRequestMethod() sebagai gantinya. Tetapi jika Anda mencoba menggunakan koneksi untuk output, Anda masih perlu mengaturnya URLConnection#setDoOutput() untuk true.

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

Bagaimanapun, jika sisi lain adalah a HttpServlet, lalu itu doPost() metode akan dipanggil dan parameter akan tersedia oleh HttpServletRequest#getParameter().


Sebenarnya menembakan permintaan HTTP

Anda dapat memecat permintaan HTTP secara eksplisit dengan URLConnection#connect(), tetapi permintaan akan secara otomatis diaktifkan saat Anda ingin mendapatkan informasi apa pun tentang respons HTTP, seperti yang digunakan oleh respons URLConnection#getInputStream()dan seterusnya. Contoh di atas tidak persis seperti itu, jadi connect() panggilan sebenarnya tidak berguna.


Mengumpulkan informasi respons HTTP

  1. Status respons HTTP:

    Anda membutuhkan sebuah HttpURLConnection sini. Cast terlebih dahulu jika perlu.

    int status = httpConnection.getResponseCode();
    
  2. Header respons HTTP:

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

    Ketika Content-Type mengandung a charset parameter, maka tubuh respon kemungkinan berbasis teks dan kami ingin memproses tubuh respons dengan pengkodean karakter sisi-server yang ditentukan kemudian.

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

Mempertahankan sesi

Sesi sisi server biasanya didukung oleh cookie. Beberapa formulir web mengharuskan Anda masuk dan / atau dilacak oleh suatu sesi. Anda dapat menggunakan CookieHandler API untuk memelihara cookie. Anda perlu mempersiapkan CookieManager dengan CookiePolicy dari ACCEPT_ALL sebelum mengirim semua permintaan 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();
// ...

Perhatikan bahwa ini diketahui tidak selalu berfungsi dengan baik dalam semua keadaan. Jika gagal untuk Anda, maka yang terbaik adalah secara manual mengumpulkan dan mengatur header cookie. Anda pada dasarnya harus mengambil semua Set-Cookie header dari respons login atau yang pertama GET meminta dan kemudian meneruskannya melalui permintaan berikutnya.

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

Itu split(";", 2)[0] ada untuk menyingkirkan atribut cookie yang tidak relevan untuk sisi server seperti expires, path, dll. Atau, Anda juga bisa menggunakan cookie.substring(0, cookie.indexOf(';')) dari pada split().


Mode Streaming

Itu HttpURLConnection akan secara default buffer seluruh meminta badan sebelum benar-benar mengirimnya, terlepas dari apakah Anda telah menetapkan panjang konten tetap yang Anda gunakan sendiri connection.setRequestProperty("Content-Length", contentLength);. Ini dapat menyebabkan OutOfMemoryExceptions setiap kali Anda secara bersamaan mengirim permintaan POST besar (mis. mengunggah file). Untuk menghindari ini, Anda ingin mengatur HttpURLConnection#setFixedLengthStreamingMode().

httpConnection.setFixedLengthStreamingMode(contentLength);

Tetapi jika panjang konten benar-benar tidak diketahui sebelumnya, maka Anda dapat menggunakan mode streaming chunked dengan mengatur HttpURLConnection#setChunkedStreamingMode() demikian. Ini akan mengatur HTTP Transfer-Encoding tajuk ke chunked yang akan memaksa tubuh permintaan dikirim dalam potongan. Contoh di bawah ini akan mengirim tubuh dalam potongan 1KB.

httpConnection.setChunkedStreamingMode(1024);

Agen pengguna

Itu bisa terjadi itu permintaan mengembalikan respons yang tidak diharapkan, sementara itu berfungsi dengan baik dengan browser web asli. Sisi server mungkin memblokir permintaan berdasarkan pada User-Agent meminta tajuk. Itu URLConnection akan secara default mengaturnya Java/1.6.0_19 di mana bagian terakhir jelas merupakan versi JRE. Anda dapat mengganti ini sebagai berikut:

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.

Gunakan string Agen-Pengguna dari a peramban terbaru.


Penanganan kesalahan

Jika kode respons HTTP adalah 4nn (Kesalahan Klien) atau 5nn (Kesalahan Server), maka Anda mungkin ingin membaca HttpURLConnection#getErrorStream() untuk melihat apakah server telah mengirim informasi kesalahan yang berguna.

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

Jika kode respons HTTP adalah -1, maka ada yang salah dengan koneksi dan penanganan respons. Itu HttpURLConnection Implementasi dalam JRE lama agak buggy dengan menjaga koneksi tetap hidup. Anda mungkin ingin mematikannya dengan mengatur http.keepAlive properti sistem ke false. Anda dapat melakukan ini secara terprogram di awal aplikasi Anda dengan:

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

Mengunggah file

Anda biasanya akan menggunakan multipart/form-data encoding untuk konten POST campuran (data biner dan karakter). Pengkodean ini secara lebih terperinci dijelaskan dalam 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();
}

Jika sisi lain adalah a HttpServlet, lalu itu doPost() metode akan dipanggil dan bagian akan tersedia oleh HttpServletRequest#getPart() (perhatikan, jadi tidak  getParameter() dan seterusnya!). Itu getPart() Namun metode ini relatif baru, itu diperkenalkan di Servlet 3.0 (Glassfish 3, Tomcat 7, dll). Sebelum Servlet 3.0, pilihan terbaik Anda gunakan Apache Commons FileUpload untuk menguraikan a multipart/form-data permintaan. Juga lihat jawaban ini untuk contoh dari kedua FileUpload dan Servelt 3.0 mendekati.


Berurusan dengan situs HTTPS yang tidak tepercaya atau salah konfigurasi

Terkadang Anda perlu menghubungkan URL HTTPS, mungkin karena Anda menulis pengikis web. Dalam hal ini, Anda mungkin akan menghadapi javax.net.ssl.SSLException: Not trusted server certificate di beberapa situs HTTPS yang tidak menyimpan sertifikat SSL mereka terbaru, atau a java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found atau javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name di beberapa situs HTTPS yang salah dikonfigurasi.

Berikut satu kali jalan static penginisialisasi di kelas scraper web Anda harus membuat HttpsURLConnection lebih lunak untuk situs HTTPS tersebut dan dengan demikian tidak membuang pengecualian itu lagi.

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

Kata-kata terakhir

Itu Apache HttpComponents HttpClient aku s banyak lebih nyaman dalam hal ini semua :)


Mem-parsing dan mengekstrak HTML

Jika semua yang Anda inginkan adalah mengurai dan mengekstrak data dari HTML, maka lebih baik gunakan parser HTML seperti Jsoup


2525



Ketika bekerja dengan HTTP, hampir selalu lebih berguna untuk merujuk HttpURLConnection daripada kelas dasar URLConnection (sejak URLConnection adalah kelas abstrak ketika Anda meminta URLConnection.openConnection() pada URL HTTP itulah yang akan Anda dapatkan kembali).

Maka Anda dapat mengandalkan URLConnection#setDoOutput(true) untuk secara implisit mengatur metode permintaan ke POS sebagai gantinya httpURLConnection.setRequestMethod("POST") yang beberapa mungkin menemukan lebih alami (dan yang juga memungkinkan Anda untuk menentukan metode permintaan lainnya seperti TARUH, MENGHAPUS, ...).

Ini juga menyediakan konstanta HTTP yang berguna sehingga Anda dapat melakukan:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

84



Terinspirasi oleh pertanyaan ini dan lainnya di SO, saya telah membuat sumber terbuka minimal dasar-http-klien yang mewujudkan sebagian besar teknik yang ditemukan di sini.

google-http-java-client juga merupakan sumber sumber terbuka yang bagus.


49



Ada 2 opsi yang bisa Anda gunakan dengan HTTP URL Hits: GET / POST

DAPATKAN Permintaan: -

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

Permintaan POST: -

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

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

22



Saya sarankan Anda melihat kode di kevinsawicki / http-request, pada dasarnya pembungkus di atas HttpUrlConnection ini menyediakan API yang jauh lebih sederhana jika Anda hanya ingin membuat permintaan sekarang atau Anda dapat melihat sumbernya (tidak terlalu besar) untuk melihat bagaimana koneksi ditangani.

Contoh: Buat a GET permintaan dengan tipe konten application/json dan beberapa parameter kueri:

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



Saya juga sangat terinspirasi oleh respons ini.

Saya sering berada di proyek di mana saya perlu melakukan beberapa HTTP, dan saya mungkin tidak ingin membawa banyak ketergantungan pihak ke-3 (yang membawa orang lain dan seterusnya dan seterusnya, dll.)

Saya mulai menulis utilitas sendiri berdasarkan beberapa percakapan ini (tidak ada yang dilakukan):

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 {

Maka hanya ada banyak atau metode statis.

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

Kemudian posting ...

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

Nah Anda mendapatkan ide ....

Berikut ini tesnya:

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


}

Anda dapat menemukan yang lain di sini:

https://github.com/RichardHightower/boon

Tujuan saya adalah untuk menyediakan hal-hal umum yang ingin dilakukan dengan cara yang lebih mudah ...


19



Memperbarui

Klien HTTP baru dikirim dengan Java 9 tetapi sebagai bagian dari   Modul inkubator bernama jdk.incubator.httpclient. Modul inkubator adalah   sarana menempatkan API non-final di tangan pengembang sementara   Kemajuan API menuju finalisasi atau penghapusan di masa depan   melepaskan.

Di Java 9, Anda dapat mengirim a GET permintaan seperti:

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

Kemudian Anda bisa memeriksa kembali HttpResponse:

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

Karena Klien HTTP baru ini masuk java.httpclient  jdk.incubator.httpclient modul, Anda harus menyatakan ketergantungan ini pada Anda module-info.java mengajukan:

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

15



Awalnya saya disesatkan oleh ini artikel yang nikmat HttpClient.

Kemudian saya menyadari hal itu HttpURLConnection akan tetap dari ini artikel

Sesuai dengan blog Google:

Klien Apache HTTP memiliki lebih sedikit bug pada Eclair dan Froyo. Ini adalah pilihan terbaik untuk rilis ini. Untuk Gingerbread, HttpURLConnection adalah pilihan terbaik. API sederhana dan ukurannya yang kecil membuatnya sangat cocok untuk Android.

Kompresi transparan dan caching respons mengurangi penggunaan jaringan, meningkatkan kecepatan dan menghemat baterai. Aplikasi baru harus menggunakan HttpURLConnection; disitulah kita akan menghabiskan energi kita untuk maju.

Setelah membaca artikel ini dan beberapa pertanyaan tumpukan lainnya, saya yakin itu HttpURLConnection akan tetap untuk jangka waktu yang lebih lama.

Beberapa pertanyaan SE mendukung HttpURLConnections:

Di Android, buat permintaan POST dengan data Formulir Berkode URL tanpa menggunakan UrlEncodedFormEntity

HttpPost bekerja di proyek Java, bukan di Android


14



Anda juga bisa menggunakan JdkRequest dari jcabi-http (Saya seorang pengembang), yang melakukan semua ini untuk Anda, mendekorasi HttpURLConnection, menembaki permintaan HTTP dan menguraikan respons, misalnya:

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

Periksa entri blog ini untuk info lebih lanjut: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html


11