පළමුවෙන්ම වියාචනය: පළ කරන ලද කේත ස්නිපෙට් සියල්ල මූලික උදාහරණ වේ. ඔබ සුළු හැසිරවීමට අවශ්ය වේ 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¶m2=%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 ප්රතිචාර තොරතුරු රැස් කිරීම
HTTP ප්රතිචාර තත්ත්වය :
ඔබට අවශ්යයි HttpURLConnection
මෙහි . අවශ්ය නම් පළමුව එය දමන්න.
int status = httpConnection.getResponseCode();
HTTP ප්රතිචාර ශීර්ෂයන් :
for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
System.out.println(header.getKey() + "=" + header.getValue());
}
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 විග්රහකයක් භාවිතා කිරීම වඩා හොඳය