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

pertanyaan dibuat di Tue, Feb 6, 2018 12:00 AM

Penggunaan java.net.URLConnection ditanya tentang cukup sering di sini, dan tutorial Oracle juga ringkas tentang hal itu.

Tutorial itu pada dasarnya hanya menunjukkan cara menjalankan permintaan GET dan membaca responsnya. Itu tidak menjelaskan di mana saja bagaimana menggunakannya untuk antara lain melakukan permintaan POST, mengatur tajuk permintaan, membaca tajuk tanggapan, menangani cookie, mengirimkan formulir HTML, mengunggah file, dll.

Jadi, bagaimana saya bisa menggunakan java.net.URLConnection untuk menjalankan dan menangani permintaan HTTP "lanjutan"?

    
1865
11 Jawaban                              11                         

Pertama disclaimer sebelumnya: cuplikan kode yang diposting adalah semua contoh dasar. Anda harus menangani IOException s sepele dan RuntimeException s seperti NullPointerException, ArrayIndexOutOfBoundsException dan selir sendiri.


Mempersiapkan

Pertama-tama kita harus tahu setidaknya URL dan charset. Parameter bersifat opsional dan tergantung 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 format name=value dan disatukan dengan &. Anda biasanya juga akan URL-encode parameter kueri dengan charset yang ditentukan menggunakan URLEncoder#encode() .

String#format() hanya untuk kenyamanan. Saya lebih suka kalau saya akan membutuhkan operator 49910 String concatenation lebih dari dua kali.


Memecat permintaan GET HTTP dengan (opsional ) parameter kueri

Ini tugas sepele. Ini metode permintaan default.

 +

Setiap string kueri harus digabungkan ke URL menggunakan

URLConnection connection = new URL(url + "?" + query).openConnection();
connection.setRequestProperty("Accept-Charset", charset);
InputStream response = connection.getInputStream();
// ...
. Header ? dapat memberi petunjuk kepada server apa yang mengkodekan parameter yang mengkode parameter ada di. Jika Anda tidak mengirim string kueri apa pun, maka Anda dapat meninggalkan tajuk Accept-Charset. Jika Anda tidak perlu mengatur header, maka Anda bahkan bisa menggunakan Accept-Charset metode pintas.  URL#openStream()

Either way, jika pihak lain adalah

InputStream response = new URL(url).openStream();
// ...
, lalu HttpServlet metode akan dipanggil dan parameter akan tersedia dengan doGet() .

Untuk tujuan pengujian, Anda dapat mencetak isi tanggapan ke stdout seperti di bawah ini:

 HttpServletRequest#getParameter()

Memecat permintaan HTTP POST dengan parameter kueri

Mengatur

try (Scanner scanner = new Scanner(response)) {
    String responseBody = scanner.useDelimiter("\\A").next();
    System.out.println(responseBody);
}
hingga URLConnection#setDoOutput() secara implisit mengatur metode permintaan ke POST. HTTP POST standar seperti formulir web lakukan adalah tipe true di mana string kueri ditulis ke badan permintaan.

 application/x-www-form-urlencoded

Catatan: setiap kali Anda ingin mengirimkan formulir HTML secara terprogram, jangan lupa untuk mengambil

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();
// ...
pasangan dari name=value elemen ke dalam string kueri dan tentu saja juga pasangan <input type="hidden"> dari elemen name=value yang Anda inginkan untuk "tekan" secara terprogram (karena itu biasanya digunakan di sisi server untuk membedakan jika tombol ditekan dan jika demikian, mana yang).

Anda juga dapat mengirimkan <input type="submit"> yang diperoleh ke URLConnection dan gunakan HttpURLConnection . Tetapi jika Anda mencoba menggunakan koneksi untuk output, Anda masih perlu mengatur HttpURLConnection#setRequestMethod() hingga URLConnection#setDoOutput().

 true

Either way, jika pihak lain adalah

HttpURLConnection httpConnection = (HttpURLConnection) new URL(url).openConnection();
httpConnection.setRequestMethod("POST");
// ...
, lalu HttpServlet metode akan dipanggil dan parameter akan tersedia dengan doPost() .


Sebenarnya mengaktifkan permintaan HTTP

Anda dapat menjalankan permintaan HTTP secara eksplisit dengan HttpServletRequest#getParameter() , tetapi permintaan akan secara otomatis dipecat saat diminta ketika Anda ingin mendapatkan informasi tentang respons HTTP, seperti badan respons menggunakan URLConnection#connect() dan seterusnya. Contoh di atas melakukan hal itu, sehingga panggilan URLConnection#getInputStream() sebenarnya tidak perlu.


Mengumpulkan informasi respons HTTP

  1. status respons HTTP :

    Anda memerlukan connect() di sini. Keluarkan terlebih dahulu jika perlu.

     HttpURLConnection
  2. header respons HTTP :

     
    int status = httpConnection.getResponseCode();
    
  3. Pengodean respons HTTP :

    Saat

    for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
        System.out.println(header.getKey() + "=" + header.getValue());
    }
    
    berisi parameter Content-Type, maka badan respons cenderung berbasis teks dan kami ingin memproses badan respons dengan pengkodean karakter yang ditentukan sisi server.  charset

Memelihara sesi

Sesi sisi server biasanya didukung oleh cookie. Beberapa formulir web mengharuskan Anda masuk dan /atau dilacak oleh suatu sesi. Anda dapat menggunakan

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.
}
API untuk mengelola cookie . Anda perlu menyiapkan CookieHandler dengan CookieManager dari CookiePolicy sebelum mengirim semua permintaan HTTP.

 ACCEPT_ALL

Perhatikan bahwa ini diketahui tidak selalu berfungsi dengan baik dalam semua keadaan. Jika gagal untuk Anda, maka yang terbaik adalah mengumpulkan dan mengatur header cookie secara manual. Pada dasarnya Anda perlu mengambil

// 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();
// ...
header dari respons login atau permintaan Set-Cookie pertama dan kemudian meneruskannya melalui permintaan berikutnya.  GET

// 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]);
}
// ...
ada untuk menyingkirkan atribut cookie yang tidak relevan untuk sisi server seperti split(";", 2)[0], expires, dll. Atau, Anda juga dapat menggunakan path alih-alih cookie.substring(0, cookie.indexOf(';')).

Mode streaming

split() akan dengan buffer default badan permintaan seluruh sebelum benar-benar mengirimnya, terlepas dari apakah Anda telah menetapkan sendiri panjang konten yang tetap menggunakan HttpURLConnection. Ini dapat menyebabkan connection.setRequestProperty("Content-Length", contentLength); detik setiap kali Anda secara bersamaan mengirim permintaan POST besar (mis. Mengunggah file). Untuk menghindari ini, Anda ingin mengatur OutOfMemoryException .

 HttpURLConnection#setFixedLengthStreamingMode()

Tetapi jika panjang konten benar-benar tidak diketahui sebelumnya, maka Anda dapat menggunakan mode streaming chunked dengan mengatur

httpConnection.setFixedLengthStreamingMode(contentLength);
. Ini akan mengatur HTTP HttpURLConnection#setChunkedStreamingMode() tajuk ke Transfer-Encoding yang akan memaksa badan permintaan dikirim dalam bentuk potongan. Contoh di bawah ini akan mengirim tubuh dalam potongan 1KB.

 chunked

Agen-Pengguna

Dapat terjadi bahwa permintaan mengembalikan respons yang tidak terduga, sementara itu berfungsi baik dengan browser web nyata . Sisi server mungkin memblokir permintaan berdasarkan

httpConnection.setChunkedStreamingMode(1024);
header permintaan. User-Agent secara default akan mengaturnya ke URLConnection ketika bagian terakhir jelas merupakan versi JRE. Anda dapat menimpanya sebagai berikut:

 Java/1.6.0_19

Gunakan string Agen-Pengguna dari browser terbaru .


Penanganan kesalahan

Jika kode respons HTTP adalah

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.
(Kesalahan Klien) atau 4nn (Kesalahan Server), maka Anda mungkin ingin membaca 5nn untuk melihat apakah server telah mengirim informasi kesalahan yang berguna.  HttpURLConnection#getErrorStream()

Jika kode respons HTTP -1, maka ada masalah dengan koneksi dan penanganan respons. Implementasi

InputStream error = ((HttpURLConnection) connection).getErrorStream();
dalam JRE yang lebih tua agak buggy dengan menjaga koneksi tetap hidup. Anda mungkin ingin mematikannya dengan mengatur properti sistem HttpURLConnection ke http.keepAlive. Anda dapat melakukan ini secara terprogram di awal aplikasi Anda dengan:  false

Mengunggah file

Anda biasanya menggunakan

System.setProperty("http.keepAlive", "false");
pengodean untuk konten POST campuran (data biner dan karakter). Pengkodean secara lebih rinci dijelaskan dalam RFC2388 .

 multipart/form-data

Jika pihak lain adalah

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();
}
, lalu HttpServlet metode akan dipanggil dan bagian-bagian akan tersedia dengan doPost() (perhatikan, jadi tidak HttpServletRequest#getPart() dan seterusnya!). Namun metode getParameter() relatif baru, diperkenalkan di Servlet 3.0 (Glassfish 3, Tomcat 7, dll). Sebelum Servlet 3.0, pilihan terbaik Anda adalah menggunakan Apache Commons FileUpload untuk mengurai permintaan getPart(). Juga lihat jawaban ini untuk contoh dari FileUpload dan Servelt 3.0 pendekatan.


Berurusan dengan situs HTTPS yang tidak terpercaya atau salah konfigurasi

Terkadang Anda perlu menghubungkan URL HTTPS, mungkin karena Anda sedang menulis scraper web. Dalam hal ini, Anda mungkin menghadapi multipart/form-data di beberapa situs HTTPS yang tidak memperbarui sertifikat SSL mereka, atau javax.net.ssl.SSLException: Not trusted server certificate atau java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] found di beberapa situs HTTPS yang tidak terkonfigurasi.

Inisialisasi javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name sekali jalan berikut di kelas scraper web Anda harus membuat static lebih lunak untuk situs HTTPS dan karenanya tidak membuang pengecualian itu lagi.

 HttpsURLConnection

Kata-kata terakhir

Apache HttpComponents HttpClient adalah jauh lebih nyaman dalam semua ini :)


Memilah dan mengekstraksi HTML

Jika yang Anda inginkan adalah mem-parsing dan mengekstraksi data dari HTML, maka lebih baik gunakan parser HTML seperti Jsoup

2642
2018-07-26 12: 14: 04Z
  1. Anda harus menempatkan tautan apache terlebih dahulu, sehingga orang yang mencari solusi menemukannya lebih cepat;)
    2010-05-28 18: 54: 30Z
  2. @ ivanceras: Jika Anda tidak dapat mengubahnya berdasarkan informasi dalam jawaban ini, maka silakan tekan
    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);
        }
    }
    
    tetapi untukn di kanan atas.
    2011-01-21 19: 33: 49Z
  3. @ Brais: Silakan baca spesifikasi. Bagian Ask Question bukan bagian dari batas itu sendiri. Itu hanya string pemisah. Saya telah memutar kembali hasil edit Anda yang tidak valid.
    2012-10-09 13: 22: 58Z
  4. @ BalusC terima kasih banyak untuk tutorial yang begitu sempurna. Harap sertakan tajuk seperti "Aliran /koneksi penutup". Saya benar-benar bingung tentang kapan dan aliran /koneksi mana yang harus ditutup.
    2013-01-26 19: 29: 52Z
  5. Bagian yang menyedihkan adalah bahwa di Android tidak disarankan untuk menggunakan Apache -- sekarang dan HttpClient kejam. android-developers.blogspot.in/2011/09/…
    2014-04-15 05: 27: 32Z

Saat bekerja dengan HTTP, hampir selalu lebih bermanfaat untuk merujuk ke HttpURLConnection daripada kelas dasar HttpURLConnection (karena URLConnection adalah kelas abstrak ketika Anda meminta URLConnection pada URL HTTP itulah yang akan Anda dapatkan kembali).

Kemudian Anda dapat bukannya mengandalkan URLConnection.openConnection() untuk secara implisit mengatur metode permintaan ke POST alih-alih melakukan URLConnection#setDoOutput(true) yang beberapa orang mungkin menemukan lebih alami (dan yang juga memungkinkan Anda untuk menentukan metode permintaan lainnya seperti PUT , DELETE , ...).

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

 httpURLConnection.setRequestMethod("POST")     
88
2013-12-17 00: 24: 55Z
  1. setDoOutPut benar adalah masalah saya yang mengatur GET saya menjadi POST. Terima kasih
    2011-12-21 21: 32: 47Z
  2. Jika Anda mencoba menulis data ke outputstream, Anda harus masih menetapkan
    int responseCode = httpURLConnection.getResponseCode();
    
    if (responseCode == HttpURLConnection.HTTP_OK) {
    
    hingga setDoOutput() jika tidak, pengecualian dilemparkan (bahkan jika Anda true) . Untuk menjadi jelas: mengatur setRequestMethod("POST") ke URLConnection#setDoOutput(true) secara implisit menetapkan metode permintaan ke POST, tetapi pengaturan true ke POST tidak secara implisit menetapkan httpURLConnection.setRequestMethod("POST") menjadi setDoOutput().
    2012-07-31 00: 09: 44Z

Terinspirasi oleh ini dan pertanyaan lain tentang SO, saya telah membuat sumber terbuka minimal basic-http-client yang mewujudkan sebagian besar teknik yang ditemukan di sini.

google-http-java-client juga merupakan sumber daya open source yang hebat.     

50
2012-06-13 16: 37: 47Z
  1. Saya hanya berpikiran sama. Tetapi mungkin juga menyenangkan untuk memiliki barebones /perpustakaan Java sederhana yang hanya menggunakan kode URLConnection seperti yang disajikan di sini yang merangkum kode untuk metode yang lebih sederhana untuk melakukan HTTP GET, POST, dll. Perpustakaan kemudian dapat dikompilasi & dikemas sebagai JAR dan diimpor /digunakan dalam kode Java atau file kelas sumber dapat dimasukkan dalam proyek Java jika JAR eksternal tidak diinginkan. Ini bisa dilakukan dengan pustaka lain seperti Apache, dll. Tetapi lebih menyebalkan dibandingkan dengan pustaka kelas 1 file sederhana menggunakan URLConnection.
    2013-01-23 00: 24: 28Z
  2. rapidvaluesolutions.com/tech_blog/... lebih menyukai HttpURLConnection daripada HttpClient
    2015-09-25 11: 48: 25Z

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

DAPATKAN Permintaan: -

 true

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);
System.out.println(String.valueOf(http_conn.getResponseCode()));
    
23
2017-05-05 16: 40: 31Z
  1. Ada beberapa lagi: PUT, DELETE, HEAD, ...
    2015-03-26 09: 19: 48Z
  2. Bagaimana Anda bisa melihat respons JSON yang sebenarnya?
    2018-01-16 19: 01: 12Z

Saya sarankan Anda melihat kode di kevinsawicki /http-request , yang pada dasarnya merupakan pembungkus di atas

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()));
ini menyediakan API yang lebih sederhana jika Anda hanya ingin mengajukan permintaan sekarang atau Anda dapat melihat sumbernya (tidak terlalu besar) untuk melihat bagaimana koneksi ditangani.

Contoh: Buat permintaan HttpUrlConnection dengan tipe konten GET dan beberapa parameter kueri:

 application/json     
21
2014-11-24 13: 43: 51Z

Saya juga sangat terinspirasi oleh respons ini.

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

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

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

Lalu ada hanya sekelompok atau metode statis.

 
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 {

Lalu poskan ...

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

Baiklah, Anda mendapatkan idenya ....

Berikut ini tesnya:

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

Anda dapat menemukan sisanya di sini:

https://github.com/RichardHightower/boon

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

    
20
2013-10-17 05: 35: 17Z
  1. Sungguh aneh bahwa dalam metode
    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);
    
    
    }
    
    ada doPost param, yang digunakan untuk mengatur header permintaan, tetapi kemudian data ditulis dengan beberapa charset kode keras charset. Bug?
    2013-11-27 13: 48: 04Z

Perbarui

  

Klien HTTP baru dikirim dengan Java 9 tetapi sebagai bagian dari   Modul inkubator bernama IO.CHARSET. Modul inkubator adalah   sarana menempatkan API non-final di tangan pengembang sementara   API kemajuan menuju finalisasi atau penghapusan di masa depan   lepaskan.

Di Java 9, Anda dapat mengirim permintaan jdk.incubator.httpclient seperti:

 GET

Kemudian Anda dapat memeriksa

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

Karena Klien HTTP baru ini ada dalam modul

int statusCode = response.statusCode();
String responseBody = response.body(HttpResponse.asString());
java.httpclient, Anda harus mendeklarasikan ketergantungan ini di file jdk.incubator.httpclient Anda:

 module-info.java     
20
2017-11-30 15: 16: 39Z

Awalnya saya disesatkan oleh artikel ini yang disukai

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

Nanti saya menyadari bahwa HttpClient akan tetap dari artikel ini a>

Sesuai blog Google :

  

Klien HTTP Apache memiliki lebih sedikit bug di Eclair dan Froyo. Ini adalah pilihan terbaik untuk rilis ini. Untuk Gingerbread, HttpURLConnection adalah pilihan terbaik. Itu mudahAPI dan ukuran kecil membuatnya sangat cocok untuk Android.

     

Capping kompresi dan respons transparan mengurangi penggunaan jaringan, meningkatkan kecepatan, dan menghemat baterai. Aplikasi baru harus menggunakan HttpURLConnection; di sinilah kita akan menghabiskan energi kita untuk maju.

Setelah membaca ini artikel dan beberapa pertanyaan lain tentang aliran, saya yakin bahwa HttpURLConnection akan bertahan untuk jangka waktu yang lebih lama.

Beberapa pertanyaan SE yang mendukung HttpURLConnection:

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

HttpPost berfungsi di proyek Java, bukan di Android

    
16
2017-05-23 11: 55: 13Z

Anda juga dapat menggunakan HttpURLConnections dari jcabi-http (saya seorang pengembang), yang melakukan semua ini untuk Anda, menghias HttpURLConnection, mem-request permintaan HTTP dan respons parsing, misalnya:

 JdkRequest

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

    
13
2014-04-11 18: 54: 16Z
  1. Bagaimana Anda menangani cookie?
    2015-01-27 19: 08: 05Z

Ada juga OkHttp , yang merupakan klien HTTP yang efisien secara default:

  
  • Dukungan HTTP /2 memungkinkan semua permintaan ke host yang sama untuk berbagi soket.
  •   
  • Kumpulan koneksi mengurangi latensi permintaan (jika HTTP /2 tidak tersedia).
  •   
  • GZIP Transparan mengecilkan ukuran unduhan.
  •   
  • Caching respons menghindari jaringan sepenuhnya untuk permintaan ulangi.
  •   

Pertama buat instance

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

Lalu, siapkan permintaan

OkHttpClient client = new OkHttpClient();
Anda:  GET

akhirnya, gunakan

Request request = new Request.Builder()
      .url(url)
      .build();
untuk mengirim yang disiapkan OkHttpClient:  Request

Untuk detail lebih lanjut, Anda dapat berkonsultasi dengan dokumentasi OkHttp

    
13
2016-01-15 12: 06: 33Z

jika Anda menggunakan http, harap hapus baris ini

 
Response response = client.newCall(request).execute();
    
11
2017-12-20 07: 15: 18Z
urlConnection.setDoOutput(true);
sumber ditempatkan sini