HTTP ඉල්ලීම් ගිනි තැබීමට සහ හැසිරවීමට java.net.URLC සම්බන්ධතාවය භාවිතා කරන්නේ කෙසේද?


1955

භාවිතය java.net.URLConnectionකියන්නේ මෙතන ගැන බෙහෙවින් බොහෝ විට ඉල්ලා, සහ ඔරකල් නිබන්ධනය වේ ඒ ගැන සංක්ෂිප්ත.

එම නිබන්ධනය මූලික වශයෙන් පෙන්වන්නේ GET ඉල්ලීමක් ඉදිරිපත් කර ප්‍රතිචාරය කියවන්නේ කෙසේද යන්න පමණි. POST ඉල්ලීමක් සිදු කිරීම, ඉල්ලීම් ශීර්ෂයන් සැකසීම, ප්‍රතිචාර ශීර්ෂයන් කියවීම, කුකීස් සමඟ ගනුදෙනු කිරීම, HTML පෝරමයක් ඉදිරිපත් කිරීම, ගොනුවක් උඩුගත කිරීම යනාදිය වෙනත් අය අතර එය භාවිතා කරන්නේ කෙසේදැයි එය කොතැනකවත් විස්තර නොකරයි.

ඉතින්, java.net.URLConnection"උසස්" HTTP ඉල්ලීම් ඉවත් කිරීමට සහ හැසිරවීමට මා භාවිතා කරන්නේ කෙසේද?

Answers:


2716

පළමුවෙන්ම වියාචනය: පළ කරන ලද කේත ස්නිපෙට් සියල්ල මූලික උදාහරණ වේ. ඔබ සුළු හැසිරවීමට අවශ්ය වේ IOExceptionනම් සහ RuntimeExceptionඑය සමාන NullPointerException, ArrayIndexOutOfBoundsExceptionහා හවුල් ඔබ.


සූදානම් වෙමින්

අප මුලින්ම අවම වශයෙන් URL සහ අක්ෂර කට්ටලය දැන සිටිය යුතුය. පරාමිතීන් අත්‍යවශ්‍ය නොවන අතර ක්‍රියාකාරී අවශ්‍යතා මත රඳා පවතී.

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

විමසුම් පරාමිතීන් name=valueආකෘතියෙන් විය යුතු අතර ඒවා සංයුක්ත කළ යුතුය &. ඔබ සාමාන්‍යයෙන් නිශ්චිත අක්ෂර කට්ටලය භාවිතයෙන් විමසුම් පරාමිතීන් URL- කේතනය කරයි URLEncoder#encode().

මෙම String#format()පමණක් පහසුව සඳහා වේ. මට +ඊට වඩා දෙවරකට වඩා සංගීත සම්මුති ක්‍රියාකරු අවශ්‍ය වූ විට මම කැමතියි .


විමසුම් පරාමිතීන් සමඟ HTTP GET ඉල්ලීමක් වෙඩි තැබීම

එය ඉතා සුළු කාර්යයකි. එය පෙරනිමි ඉල්ලීම් ක්‍රමයයි.

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

ඕනෑම විමසුම් නූලක් භාවිතයෙන් URL එකට සම්බන්ධ කළ යුතුය ?. මෙම Accept-Charsetශීර්ෂ පරාමිතීන් සිටින දේ සංකේතවත්. ඔබ යම් විමසුමක් string යවන්න එපා නම්, ඔබ තැබිය හැක සේවාදායකය ඇතුලත් විය හැක Accept-Charsetඉවත් ශීර්ෂ. ඔබට කිසිදු ශීර්ෂයක් සැකසීමට අවශ්‍ය නොවේ නම්, ඔබට URL#openStream()කෙටිමං ක්‍රමය පවා භාවිතා කළ හැකිය .

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

කෙසේ හෝ අනෙක් පැත්ත a HttpServletනම්, එහි doGet()ක්‍රමය කැඳවනු ලබන අතර පරාමිතීන් ලබා ගත හැකිය HttpServletRequest#getParameter().

පරීක්ෂණ අරමුණු සඳහා, ඔබට ප්‍රතිචාර දැක්වීමේ ආයතනය පහත පරිදි stdout වෙත මුද්‍රණය කළ හැකිය:

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

විමසුම් පරාමිතීන් සමඟ HTTP POST ඉල්ලීමක් වෙඩි තැබීම

මෙම සැකසීම URLConnection#setDoOutput()සඳහා trueනිසැකයෙන්ම තැපැල් කළ ඉල්ලීම ක්රමය සකසයි. වෙබ් පෝරම වල සම්මත HTTP POST යනු application/x-www-form-urlencodedවිමසුම් දාමය ඉල්ලීම් ශරීරයට ලියා ඇති ආකාරයේ ය.

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

සටහන: ඔබ ක්‍රමලේඛනගතව HTML පෝරමයක් ඉදිරිපත් කිරීමට කැමති විට name=value, ඕනෑම <input type="hidden">මූලද්‍රව්‍යයක යුගල විමසුම් නූලට ගෙන යාමට අමතක නොකරන්න . ඇත්ත වශයෙන්ම ඔබ ක්‍රමලේඛනගතව “ඔබන්න” කැමති මූලද්‍රව්‍ය name=valueයුගලය <input type="submit">(මන්ද බොත්තමක් එබූ විට සහ එසේ නම්, කුමන එකද යන්න වෙන්කර හඳුනා ගැනීම සඳහා එය සාමාන්‍යයෙන් සේවාදායක පැත්තේ භාවිතා වේ.

ඔබට ලබාගත් URLConnectionදේ වාත්තු HttpURLConnectionකර HttpURLConnection#setRequestMethod()ඒ වෙනුවට භාවිතා කළ හැකිය. නමුත් ඔබ ප්‍රතිදානය සඳහා සම්බන්ධතාවය භාවිතා කිරීමට උත්සාහ කරන්නේ නම් ඔබ තවමත් සැකසිය URLConnection#setDoOutput()යුතුය true.

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

කෙසේ හෝ අනෙක් පැත්ත a නම් HttpServletනම්, එහි doPost()ක්‍රමය කැඳවනු ලබන අතර පරාමිතීන් ලබා ගත හැකිය HttpServletRequest#getParameter().


ඇත්තටම HTTP ඉල්ලීම ඉවත් කිරීම

ඔබට HTTP ඉල්ලීම පැහැදිලිවම වෙඩි තැබිය හැකිය URLConnection#connect() , නමුත් ඔබට HTTP ප්‍රතිචාරය පිළිබඳ කිසියම් තොරතුරක් ලබා ගැනීමට අවශ්‍ය වූ විට ඉල්ලීම ස්වයංක්‍රීයව ඉල්ලීම URLConnection#getInputStream()මත ක්‍රියාත්මක වේ. ඉහත උදාහරණ හරියටම එය කරයි, එබැවින් connect()ඇමතුම ඇත්ත වශයෙන්ම අතිරික්තය.


HTTP ප්‍රතිචාර තොරතුරු රැස් කිරීම

  1. HTTP ප්‍රතිචාර තත්ත්වය :

    ඔබට අවශ්‍යයි HttpURLConnection මෙහි . අවශ්‍ය නම් පළමුව එය දමන්න.

    int status = httpConnection.getResponseCode();
  2. HTTP ප්‍රතිචාර ශීර්ෂයන් :

    for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
        System.out.println(header.getKey() + "=" + header.getValue());
    }
  3. HTTP ප්‍රතිචාර කේතන :

    පරාමිතියක් Content-Typeඅඩංගු වූ විට charset, ප්‍රතිචාරය ශරීරය පෙළ මත පදනම් විය හැකි අතර ප්‍රතිචාර පැත්තේ සේවාදායකයේ විශේෂිත අක්ෂර කේතීකරණය සමඟ සැකසීමට අපි කැමැත්තෙමු.

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

සැසිය පවත්වා ගැනීම

සේවාදායක පැත්තේ සැසිය සාමාන්‍යයෙන් කුකියක් විසින් අනුබල දෙනු ලැබේ. සමහර වෙබ් පෝරම සඳහා ඔබ පුරනය වී ඇති අතර / හෝ සැසියක් මගින් නිරීක්ෂණය කළ යුතුය. CookieHandlerකුකී නඩත්තු කිරීමට ඔබට API භාවිතා කළ හැකිය . ඔබ සූදානම් විය යුතුයි CookieManagerසමඟ CookiePolicyවන ACCEPT_ALLසියළු 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();
// ...

මෙය සෑම අවස්ථාවකම නිසි ලෙස ක්‍රියා නොකරන බව දන්නා බව සලකන්න. එය ඔබට අසමත් වුවහොත්, හොඳම වන්නේ කුකී ශීර්ෂයන් අතින් එකතු කර සකස් කිරීමයි. ඔබ මූලිකවම Set-Cookieපිවිසුම් ප්‍රතිචාරයෙන් හෝ පළමු 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]);
}
// ...

මෙම split(";", 2)[0]වැනි සේවාදායකය පැත්තට අනදාල වන කුකී ගුණාංග එහි මිදෙන්නට වේ expires, pathඊට අමතරව ආදිය,, ඔබ ද භාවිතා කළ හැකි cookie.substring(0, cookie.indexOf(';'))වෙනුවට split().


ප්‍රවාහ ප්‍රකාරය

මෙම HttpURLConnectionපෙරනිමි විසින් කැමැත්ත ප්රේරක සමස්ත ඉල්ලීම ශරීරය ඇත්තටම නොතකා ඔබ භාවිතා ස්ථාවර අන්තර්ගතයට දිග තබා තියෙනවා යන්න, එය යැවීමට පෙර connection.setRequestProperty("Content-Length", contentLength);. OutOfMemoryExceptionඔබ සමගාමීව විශාල POST ඉල්ලීම් යවන සෑම අවස්ථාවකම මෙය හේතු විය හැක (උදා: ගොනු උඩුගත කිරීම). මෙය වළක්වා ගැනීම සඳහා, ඔබ එය සැකසීමට කැමතියි HttpURLConnection#setFixedLengthStreamingMode().

httpConnection.setFixedLengthStreamingMode(contentLength);

නමුත් අන්තර්ගතයේ දිග කලින් දැන නොසිටින්නේ නම්, ඒ HttpURLConnection#setChunkedStreamingMode()අනුව සැකසීමෙන් ඔබට කැබලි කළ ප්‍රවාහ ක්‍රමය භාවිතා කළ හැකිය . මෙමඟින් HTTP Transfer-Encodingශීර්ෂය සකසනු ඇති chunkedඅතර එමඟින් ඉල්ලීම් ශරීරය කැබලිවලට යැවීමට බල කෙරෙනු ඇත. පහත උදාහරණයෙන් ශරීරය 1KB කැබලිවලට යවනු ලැබේ.

httpConnection.setChunkedStreamingMode(1024);

පරිශීලක-නියෝජිත

සැබෑ වෙබ් බ්‍රව්සරයක් සමඟ ඉල්ලීමක් අනපේක්ෂිත ප්‍රතිචාරයක් ලබා දෙන අතර එය සිදුවිය හැකිය . සේවාදායක පාර්ශවය බොහෝ විට ඉල්ලීම් User-Agentශීර්ෂය මත පදනම්ව ඉල්ලීම් අවහිර කරයි. මෙම URLConnectionපෙරනිමි විසින් කැමැත්ත ලෙස සකස් කර Java/1.6.0_19අවසන් කොටස පැහැදිලිවම JRE අනුවාදය කොහෙද. ඔබට මෙය පහත පරිදි අභිබවා යා හැකිය:

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.

මෑත බ්‍රව්සරයකින් පරිශීලක-නියෝජිත නූල භාවිතා කරන්න .


හැසිරවීමේ දෝෂයකි

HTTP ප්‍රතිචාර කේතය 4nn(සේවාලාභී දෝෂය) හෝ 5nn(සේවාදායක දෝෂය) HttpURLConnection#getErrorStream()නම්, සේවාදායකයා කිසියම් ප්‍රයෝජනවත් දෝෂ තොරතුරු යවා ඇත්දැයි බැලීමට ඔබට කියවීමට අවශ්‍ය විය හැකිය .

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

HTTP ප්‍රතිචාර කේතය -1 නම්, සම්බන්ධතාවය හා ප්‍රතිචාර හැසිරවීමේදී යමක් වැරදී ඇත. මෙම HttpURLConnectionක්රියාත්මක කිරීම සම්බන්ධතා ජීවමානව පවත්වාගෙන සමග තරමක් සපිරි පැරණි JREs වේ. http.keepAliveපද්ධති දේපල සැකසීමෙන් ඔබට එය අක්‍රිය කිරීමට අවශ්‍ය විය හැකිය false. ඔබගේ යෙදුමේ ආරම්භයේ දී ඔබට මෙය ක්‍රමලේඛිකව කළ හැකිය:

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

ගොනු උඩුගත කිරීම

ඔබ සාමාන්‍යයෙන් multipart/form-dataමිශ්‍ර POST අන්තර්ගතයන් (ද්විමය සහ අක්‍ෂර දත්ත) සඳහා කේතන ක්‍රමයක් භාවිතා කරයි . කේතනය වඩාත් විස්තරාත්මකව 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();
}

අනෙක් පැත්ත a HttpServletනම්, එහි doPost()ක්‍රමවේදය කැඳවනු ලබන අතර කොටස් ලබා ගත හැකිය HttpServletRequest#getPart()(සටහන, මේ අනුව එසේ නොවේ getParameter() !). මෙම getPart()ක්‍රමය කෙසේ වෙතත් සාපේක්ෂව නව ය, එය සර්වට් 3.0 (ග්ලාස්ෆිෂ් 3, ටොම්කාට් 7, ආදිය) මගින් හඳුන්වා දී ඇත. සර්වට් 3.0 ට පෙර, ඔබේ හොඳම තේරීම වන්නේ ඉල්ලීමක් විග්‍රහ කිරීම සඳහා අපාචේ කොමන්ස් ෆයිල්අප්ලෝඩ් භාවිතා කිරීමයි multipart/form-data. FileUpload සහ Servelt 3.0 ප්‍රවේශයන් සඳහා උදාහරණ සඳහා මෙම පිළිතුර බලන්න .


විශ්වාසදායක හෝ වැරදි ලෙස වින්‍යාසගත කර ඇති HTTPS අඩවි සමඟ කටයුතු කිරීම

සමහර විට ඔබ වෙබ් සීරීමක් ලියන නිසා HTTPS URL එකක් සම්බන්ධ කිරීමට අවශ්‍ය වේ. එවැනි අවස්ථාවකදී, javax.net.ssl.SSLException: Not trusted server certificateසමහර SSTPS අඩවි වල SSL සහතික යාවත්කාලීනව තබා නොගන්නා හෝ ඔබට java.security.cert.CertificateException: No subject alternative DNS name matching [hostname] foundහෝjavax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name වැරදි ලෙස වින්‍යාසගත කර ඇති HTTPS අඩවි වලට ඇත.

staticඔබේ වෙබ් සීරීම් පන්තියේ පහත දැක්වෙන එක් වරක් ක්‍රියාත්මක වන ආරම්භකය HttpsURLConnectionඑම HTTPS අඩවි වලට වඩා සැහැල්ලු විය යුතු අතර එමඟින් එම ව්‍යතිරේකයන් තවදුරටත් විසි නොකරන්න.

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

අවසාන වචන

මෙම HttpComponents HttpClient Apache වන බොහෝ මේ සියල්ල වඩාත් පහසු :)


HTML විග්‍රහ කිරීම සහ උපුටා ගැනීම

ඔබට අවශ්‍ය වන්නේ HTML වෙතින් දත්ත විග්‍රහ කිරීම සහ උපුටා ගැනීම නම්, Jsoup වැනි HTML විග්‍රහකයක් භාවිතා කිරීම වඩා හොඳය


119
ඔබ මුලින්ම
අපාචේ

40
anceivanceras: මෙම පිළිතුරේ ඇති තොරතුරු මත පදනම්ව ඔබට එය තම්බා ගත නොහැකි නම්, කරුණාකර Ask Questionදකුණු පස ඇති බොත්තම ඔබන්න.
BalusC

3
Ra බ්රයිස්: කරුණාකර පිරිවිතර කියවන්න. මෙම --කොටස මායිම් ම කොටසක් නොවේ. එය බෙදුම් නූලක් පමණි. මම ඔබේ අවලංගු සංස්කරණය පෙරළා දැමුවෙමි.
BalusC

7
එවැනි පරිපූර්ණ නිබන්ධනයක් සඳහා alBalusC බොහෝම ස්තූතියි. කරුණාකර "ධාරාවන් වසා දැමීම / සම්බන්ධතා" වැනි ශීර්ෂයක් ද ඇතුළත් කරන්න. වසා දැමිය යුත්තේ කවදාද සහ කුමන ප්‍රවාහයන්ද යන්න පිළිබඳව මම ඇත්තටම ව්‍යාකූල වී සිටිමි.

10
කනගාටුදායක කාරණය නම් ඇන්ඩ්‍රොයිඩ් හි දැන් අපාචේ භාවිතා කිරීම නිර්දේශ කර නොමැතිHttpClient අතර HttpURLConnectionඑය කුරිරු ය. android-developers.blogspot.in/2011/09/…
yati sagade

91

HTTP සමඟ වැඩ කරන විට එය HttpURLConnectionමූලික පන්තියට වඩා යොමු කිරීම සැමවිටම ප්‍රයෝජනවත් වේ URLConnection( URLConnectionඔබ URLConnection.openConnection()HTTP URL එකක් ඉල්ලන විට එය වියුක්ත පන්තියක් බැවින් ඔබට කෙසේ හෝ ආපසු ලැබෙනු ඇත).

එවිට ඔබට URLConnection#setDoOutput(true)ඉල්ලීම් ක්‍රමය POST වෙත ව්‍යංගයෙන් සැකසීමට විශ්වාසය තැබීම වෙනුවට httpURLConnection.setRequestMethod("POST")සමහරුන්ට වඩාත් ස්වාභාවික යැයි සිතිය හැකි දේ කරන්න (තවද PUT , DELETE වැනි වෙනත් ඉල්ලීම් ක්‍රම නියම කිරීමටද ඔබට ඉඩ සලසයි. , ... ).

එය ප්‍රයෝජනවත් HTTP නියතයන් ද සපයන බැවින් ඔබට මෙය කළ හැකිය:

int responseCode = httpURLConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

1
setDoOutPut සත්‍යය නම් මගේ ගැටළුව POST වෙත යොමු කිරීමයි. ස්තූතියි
පැට්‍රික් කෆ්කා

22
ඔබ outputstream ලිවීමේ දත්ත කිරීමට උත්සාහ කරන්නේ නම් ඔබට කළ යුතුය තවමත් සකස් setDoOutput()කිරීමට true(පවා ඔබ නම්, වෙනත් ආකාරයකින් ව්යතිරේකයක් දමන setRequestMethod("POST")). පැහැදිලි කිරීමට: සැකසීම URLConnection#setDoOutput(true)සඳහා trueනිසැකයෙන්ම තැපැල් කළ ඉල්ලීම ක්රමය සකසයි, නමුත් සැකසුම httpURLConnection.setRequestMethod("POST")තනතුරට කරන්නේ නැහැ නිසැකයෙන්ම සකස් setDoOutput()කිරීමට true.
ටෝනි චාන්

54

SO හි මෙම සහ වෙනත් ප්‍රශ්න වලින් ආශ්වාදයක් ලබා ගත් මම මෙහි ඇති බොහෝ ශිල්පීය ක්‍රමෝපායන් මූර්තිමත් කරන අවම විවෘත මූලාශ්‍ර මූලික-http-client එකක් නිර්මාණය කර ඇත්තෙමි .

google-http-java-client ද විශිෂ්ට විවෘත මූලාශ්‍ර සම්පතකි.


මම හිතුවේ එකම දෙයක්. නමුත් මෙහි ඉදිරිපත් කර ඇති පරිදි යූආර්එල්සී සම්බන්ධතා කේතය පමණක් භාවිතා කරන හිස් කබල් / සරල ජාවා පුස්තකාලයක් තිබීම සතුටක් විය හැකිය. එමඟින් කේතය HTTP GET, POST යනාදිය සඳහා සරල ක්‍රමවේදයන් සමඟ සංයුක්ත කරයි. පුස්තකාලය JAR ලෙස ඇසුරුම් කර ඇසුරුම් කළ හැකිය. බාහිර JARs අවශ්‍ය නොවන්නේ නම් ජාවා කේතයට ආනයනය / භාවිතා කිරීම හෝ ප්‍රභව පන්ති ගොනුව ජාවා ව්‍යාපෘතියට ඇතුළත් කළ හැකිය. මෙය Apache වැනි වෙනත් පුස්තකාල සමඟ කළ හැකි නමුත් URLConnection භාවිතා කරන සරල 1 ගොනු පන්ති පුස්තකාලයකට සාපේක්ෂව වැඩි වේදනාවක් ගෙන දේ.
ඩේවිඩ්

rapidvaluesolutions.com/tech_blog/… HttpClient හරහා HttpURLC සම්බන්ධතාවයට කැමැත්තක් දක්වයි
රවින්ද්‍ර

24

Kevinsawicki / http-request මත ඇති කේතය දෙස බැලීමට මම ඔබට යෝජනා කරමි .HttpUrlConnection ඔබට ඉල්ලීම් කිරීමට අවශ්‍ය නම් හෝ ඔබට ප්‍රභවයන් දෙස බැලීමට හැකි නම් වඩාත් සරල API එකක් සපයයි. එය ඉතා විශාල නොවේ) සම්බන්ධතා හසුරුවන ආකාරය බැලීමට.

උදාහරණය: GETඅන්තර්ගත වර්ගය application/jsonසහ විමසුම් පරාමිතීන් සමඟ ඉල්ලීමක් කරන්න :

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

24

ඔබට HTTP URL පහර සමඟ යා හැකි විකල්ප 2 ක් ඇත: GET / 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()));

තැපැල් ඉල්ලීම: -

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

3
සත්‍ය JSON ප්‍රතිචාරය ඔබ දකින්නේ කෙසේද?
සෝරා

21

මෙම ප්‍රතිචාරයෙන් මා ද මහත් ආශ්වාදයක් ලැබීය.

මම බොහෝ විට HTTP කිහිපයක් කළ යුතු ව්‍යාපෘතිවල සිටින අතර, තෙවන පාර්ශවීය යැපීම් රාශියක් ගෙන ඒමට මට අවශ්‍ය නොවනු ඇත (ඒවා අනෙක් අය ගෙන එනු ඇත. යනාදිය)

මෙම සමහර සංවාද මත පදනම්ව මම මගේම උපයෝගීතා ලිවීමට පටන් ගතිමි (කිසිවක් සිදු නොවූ තැනක):

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 {

එවිට ඇත්තේ පොකුරක් හෝ ස්ථිතික ක්‍රම පමණි.

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

ඉන්පසු පළ කරන්න ...

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

හොඳයි ඔබට අදහස ලැබෙනවා ....

පරීක්ෂණ මෙන්න:

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


}

ඉතිරි කොටස ඔබට මෙහි සොයාගත හැකිය:

https://github.com/RichardHightower/boon

මගේ පරමාර්ථය නම් යමෙකුට කිරීමට අවශ්‍ය පොදු දේ පසුව වඩාත් පහසු ආකාරයකින් සැපයීමයි ....


2
doPostක්‍රමයේ charsetපරාමිතියක් තිබීම අමුතු දෙයක් වන අතර එය ඉල්ලීම් ශීර්ෂකය සැකසීමට භාවිතා කරයි, නමුත් පසුව දත්ත ලියා ඇත්තේ දෘඩ කේත සහිත අක්ෂර කට්ටලයක් සමඟ ය IO.CHARSET. දෝෂයක්?
Vud Khudenko

21

යාවත්කාලීන කරන්න

නව HTTP සේවාදායකයා ජාවා 9 සමඟ නැව්ගත කර ඇති නමුත් ඉන්කියුබේටර් මොඩියුලයේ කොටසක් ලෙස නම් කර jdk.incubator.httpclientඇත. ඉන්කියුබේටර් මොඩියුල යනු අවසාන නොවන ඒපීඅයි සංවර්ධකයින් අතට පත් කිරීමේ මාධ්‍යයක් වන අතර ඒපීඅයි අනාගත නිකුතුවකදී අවසන් කිරීම හෝ ඉවත් කිරීම කරා ඉදිරියට යයි.

ජාවා 9 හි, ඔබට GETඉල්ලීමක් එවිය හැකිය :

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

එවිට ඔබට ආපසු පැමිණි අය පරීක්ෂා කළ හැකිය HttpResponse:

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

මෙම නව HTTP සේවාදායකයා සිටින බැවින් java.httpclient jdk.incubator.httpclientමොඩියුලය, ඔබේ module-info.javaගොනුවේ මෙම පරායත්තතාවය ප්‍රකාශ කළ යුතුය :

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

1
වැඩිදුර යාවත්කාලීන කිරීම: මොඩියුලය පුර්ව ලියාපදිංචි තක්සේරු තත්වයෙන් බැහැර ය. එය දැන් java.net.http මිස jdk.incubator.httpclient නොවේ.
වී.ජී.ආර්

17

මුලදී මා කැමති මෙම ලිපියෙන් මාව නොමඟ යවන ලදි HttpClient.

HttpURLConnectionමෙම ලිපියෙන් එය ඉවත්ව යන බව පසුව මට වැටහුණි

ගූගල් බ්ලොග් අඩවියට අනුව :

Apache HTTP සේවාදායකයාට Eclair සහ Froyo හි අඩු දෝෂ තිබේ. මෙම නිකුතු සඳහා හොඳම තේරීම එයයි. ජින්ජර් බ්‍රෙඩ් සඳහා, HttpURLC සම්බන්ධතාවය හොඳම තේරීම වේ. එහි සරල API සහ කුඩා ප්‍රමාණය නිසා එය ඇන්ඩ්‍රොයිඩ් සඳහා සුදුසු වේ.

විනිවිද පෙනෙන සම්පීඩනය සහ ප්‍රතිචාර හැඹිලිය ජාල භාවිතය අඩු කරයි, වේගය වැඩි කරයි සහ බැටරිය ඉතිරි කරයි. නව යෙදුම් HttpURLC සම්බන්ධතාවය භාවිතා කළ යුතුය; අපේ ශක්තිය ඉදිරියට ගෙනයන්නේ එහිදීය.

මෙම ලිපිය සහ ප්‍රවාහ ප්‍රශ්න පිළිබඳ තවත් කරුණු කිහිපයක් කියවීමෙන් පසුව , HttpURLConnectionඑය වැඩි කාලයක් පවතිනු ඇතැයි මට විශ්වාසයි .

සමහර SE ප්‍රශ්න වලට කැමති HttpURLConnections:

ඇන්ඩ්‍රොයිඩ් හි, UrlEncodedFormEntity භාවිතා නොකර URL සංකේතාත්මක පෝරම දත්ත සමඟ POST ඉල්ලීමක් කරන්න

HttpPost වැඩ කරන්නේ ජාවා ව්‍යාපෘතියේ මිස ඇන්ඩ්‍රොයිඩ් වල නොවේ


15

පෙරනිමියෙන් කාර්යක්ෂම වන HTTP සේවාදායකයකු වන OkHttp ද ඇත :

  • HTTP / 2 සහය එකම ධාරකයට කරන සියලුම ඉල්ලීම් සොකට් එකක් බෙදා ගැනීමට ඉඩ දෙයි.
  • සම්බන්ධතා සංචිතය මඟින් ඉල්ලීම් ප්‍රමාදය අඩු කරයි (HTTP / 2 නොමැති නම්).
  • විනිවිද පෙනෙන GZIP බාගත කිරීම් ප්‍රමාණය අඩු කරයි.
  • ප්‍රතිචාර හැඹිලිය නැවත නැවත ඉල්ලීම් සඳහා ජාලය සම්පූර්ණයෙන්ම මග හැරේ.

මුලින්ම උදාහරණයක් සාදන්න OkHttpClient:

OkHttpClient client = new OkHttpClient();

ඉන්පසු, ඔබේ GETඉල්ලීම සූදානම් කරන්න :

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

අවසාන වශයෙන්, OkHttpClientසූදානම් යැවීමට භාවිතා කරන්න Request:

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

වැඩි විස්තර සඳහා, ඔබට OkHttp හි ප්‍රලේඛනය විමසිය හැකිය


14

ඔබ ද භාවිතා කළ හැකිය JdkRequestසිට jcabi-http , ඔබ මේ සියලු වැඩ කටයුතු කරන්නේ වන, සැරසීම HttpURLConnection (මම සංවර්ධක ඉන්නේ) උදාහරණයක් ලෙස, HTTP ඉල්ලීම් සහ මාණකරනය ක්රියාත්මක ප්රතිචාර වෙඩි:

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

වැඩි විස්තර සඳහා මෙම බ්ලොග් සටහන පරීක්ෂා කරන්න: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html


1
ඔබ කුකීස් හසුරුවන්නේ කෙසේද?
ඩෙජෙල්

12

ඔබ http භාවිතා කරන්නේ නම් කරුණාකර මෙම රේඛාව ඉවත් කරන්න

urlConnection.setDoOutput(true);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.