1. ภาพรวม
ในบทช่วยสอนฉบับย่อนี้เรานำเสนอวิธีการดำเนินการตามคำขอ HTTP ใน Javaโดยใช้คลาส Java HttpUrlConnection
โปรดทราบว่าเริ่มต้นด้วย JDK 11 Java ให้ใหม่ API สำหรับการดำเนินการร้องขอ HTTP ซึ่งเป็นความหมายแทนการHttpUrlConnection, HttpClient API
2. HttpUrlConnection
HttpUrlConnectionชั้นช่วยให้เราสามารถดำเนินการร้องขอ HTTP ขั้นพื้นฐานโดยไม่ต้องใช้ห้องสมุดใด ๆ เพิ่มเติม คลาสทั้งหมดที่เราต้องการเป็นส่วนหนึ่งของแพ็คเกจjava.net
ข้อเสียของการใช้วิธีนี้คือโค้ดอาจยุ่งยากกว่าไลบรารี HTTP อื่น ๆ และไม่มีฟังก์ชันขั้นสูงเช่นวิธีเฉพาะสำหรับการเพิ่มส่วนหัวหรือการพิสูจน์ตัวตน
3. การสร้างคำขอ
เราสามารถสร้างอินสแตนซ์HttpUrlConnectionโดยใช้เมธอด openConnection ()ของคลาสURL โปรดทราบว่าวิธีนี้สร้างเฉพาะวัตถุการเชื่อมต่อ แต่ยังไม่สร้างการเชื่อมต่อ
HttpUrlConnectionชั้นใช้สำหรับทุกประเภทของการร้องขอโดยการตั้งค่าrequestMethodแอตทริบิวต์หนึ่งของค่า: GET, POST ศีรษะ OPTIONS, PUT ลบ TRACE
มาสร้างการเชื่อมต่อกับ URL ที่กำหนดโดยใช้เมธอด GET:
URL url = new URL("//example.com"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET");
4. การเพิ่มพารามิเตอร์คำขอ
หากเราต้องการเพิ่มพารามิเตอร์ให้กับคำขอเราต้องตั้งค่าคุณสมบัติdoOutput เป็น trueจากนั้นเขียนสตริงของรูปแบบparam1 = value¶m2 = valueไปยังOutputStreamของอินสแตนซ์HttpUrlConnection :
Map parameters = new HashMap(); parameters.put("param1", "val"); con.setDoOutput(true); DataOutputStream out = new DataOutputStream(con.getOutputStream()); out.writeBytes(ParameterStringBuilder.getParamsString(parameters)); out.flush(); out.close();
เพื่ออำนวยความสะดวกในการแปลงพารามิเตอร์ Mapเราได้เขียนคลาสยูทิลิตี้ที่เรียกว่าParameterStringBuilderซึ่งมีเมธอดแบบคงที่getParamsString ()ซึ่งจะแปลงMapเป็นสตริงของรูปแบบที่ต้องการ:
public class ParameterStringBuilder { public static String getParamsString(Map params) throws UnsupportedEncodingException{ StringBuilder result = new StringBuilder(); for (Map.Entry entry : params.entrySet()) { result.append(URLEncoder.encode(entry.getKey(), "UTF-8")); result.append("="); result.append(URLEncoder.encode(entry.getValue(), "UTF-8")); result.append("&"); } String resultString = result.toString(); return resultString.length() > 0 ? resultString.substring(0, resultString.length() - 1) : resultString; } }
5. การตั้งค่าส่วนหัวของคำขอ
การเพิ่มส่วนหัวในคำขอสามารถทำได้โดยใช้เมธอด setRequestProperty () :
con.setRequestProperty("Content-Type", "application/json");
ในการอ่านค่าของส่วนหัวจากการเชื่อมต่อเราสามารถใช้เมธอดgetHeaderField () :
String contentType = con.getHeaderField("Content-Type");
6. การกำหนดค่าการหมดเวลา
คลาสHttpUrlConnectionอนุญาตให้ตั้งค่าการเชื่อมต่อและการหมดเวลาอ่าน ค่าเหล่านี้กำหนดช่วงเวลาเพื่อรอการเชื่อมต่อกับเซิร์ฟเวอร์ที่จะสร้างขึ้นหรือข้อมูลพร้อมสำหรับการอ่าน
ในการตั้งค่าการหมดเวลาเราสามารถใช้เมธอด setConnectTimeout ()และsetReadTimeout () :
con.setConnectTimeout(5000); con.setReadTimeout(5000);
ในตัวอย่างเราตั้งค่าการหมดเวลาทั้งสองเป็นห้าวินาที
7. การจัดการคุกกี้
java.netแพคเกจประกอบด้วยชั้นเรียนที่สะดวกในการทำงานร่วมกับคุกกี้เช่นCookieManagerและHttpCookie
ขั้นแรกในการอ่านคุกกี้จากการตอบกลับเราสามารถดึงค่าของส่วนหัวSet-Cookieและแยกวิเคราะห์ไปยังรายการวัตถุHttpCookie :
String cookiesHeader = con.getHeaderField("Set-Cookie"); List cookies = HttpCookie.parse(cookiesHeader);
ต่อไปเราจะเพิ่มคุกกี้ในที่เก็บคุกกี้ :
cookies.forEach(cookie -> cookieManager.getCookieStore().add(null, cookie));
ตรวจสอบว่ามีคุกกี้ที่เรียกว่าชื่อผู้ใช้อยู่หรือไม่และหากไม่มีเราจะเพิ่มลงในที่เก็บคุกกี้ด้วยค่า "john"
Optional usernameCookie = cookies.stream() .findAny().filter(cookie -> cookie.getName().equals("username")); if (usernameCookie == null) { cookieManager.getCookieStore().add(null, new HttpCookie("username", "john")); }
สุดท้ายในการเพิ่มคุกกี้ในคำขอเราจำเป็นต้องตั้งค่าส่วนหัวคุกกี้หลังจากปิดและเปิดการเชื่อมต่ออีกครั้ง:
con.disconnect(); con = (HttpURLConnection) url.openConnection(); con.setRequestProperty("Cookie", StringUtils.join(cookieManager.getCookieStore().getCookies(), ";"));
8. การจัดการการเปลี่ยนเส้นทาง
เราสามารถเปิดหรือปิดใช้งานโดยอัตโนมัติตามการเปลี่ยนเส้นทางสำหรับการเชื่อมต่อเฉพาะโดยใช้เมธอด setInstanceFollowRedirects ()พร้อมพารามิเตอร์trueหรือfalse :
con.setInstanceFollowRedirects(false);
นอกจากนี้ยังสามารถเปิดหรือปิดการเปลี่ยนเส้นทางอัตโนมัติสำหรับการเชื่อมต่อทั้งหมด :
HttpUrlConnection.setFollowRedirects(false);
โดยค่าเริ่มต้นพฤติกรรมจะเปิดใช้งาน
เมื่อคำขอส่งคืนรหัสสถานะ 301 หรือ 302 ซึ่งระบุการเปลี่ยนเส้นทางเราสามารถดึงข้อมูลส่วนหัวตำแหน่งและสร้างคำขอใหม่ไปยัง URL ใหม่:
if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM) { String location = con.getHeaderField("Location"); URL newUrl = new URL(location); con = (HttpURLConnection) newUrl.openConnection(); }
9. การอ่านคำตอบ
การอ่านการตอบสนองของคำขอสามารถทำได้โดยการแยกวิเคราะห์InputStreamของอินสแตนซ์HttpUrlConnection
To execute the request, we can use the getResponseCode(), connect(), getInputStream() or getOutputStream() methods:
int status = con.getResponseCode();
Finally, let's read the response of the request and place it in a content String:
BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream())); String inputLine; StringBuffer content = new StringBuffer(); while ((inputLine = in.readLine()) != null) { content.append(inputLine); } in.close();
To close the connection, we can use the disconnect() method:
con.disconnect();
10. Reading the Response on Failed Requests
If the request fails, trying to read the InputStream of the HttpUrlConnection instance won't work. Instead, we can consume the stream provided by HttpUrlConnection.getErrorStream().
We can decide which InputStream to use by comparing the HTTP status code:
int status = con.getResponseCode(); Reader streamReader = null; if (status > 299) { streamReader = new InputStreamReader(con.getErrorStream()); } else { streamReader = new InputStreamReader(con.getInputStream()); }
And finally, we can read the streamReader in the same way as the previous section.
11. Building the Full Response
It's not possible to get the full response representation using the HttpUrlConnection instance.
However, we can build it using some of the methods that the HttpUrlConnection instance offers:
public class FullResponseBuilder { public static String getFullResponse(HttpURLConnection con) throws IOException { StringBuilder fullResponseBuilder = new StringBuilder(); // read status and message // read headers // read response content return fullResponseBuilder.toString(); } }
Here, we're reading the parts of the responses, including the status code, status message and headers, and adding these to a StringBuilder instance.
First, let's add the response status information:
fullResponseBuilder.append(con.getResponseCode()) .append(" ") .append(con.getResponseMessage()) .append("\n");
ต่อไปเราจะได้รับส่วนหัวโดยใช้getHeaderFields ()และเพิ่มแต่ละส่วนในStringBuilderของเราในรูปแบบ HeaderName: HeaderValues :
con.getHeaderFields().entrySet().stream() .filter(entry -> entry.getKey() != null) .forEach(entry -> { fullResponseBuilder.append(entry.getKey()).append(": "); List headerValues = entry.getValue(); Iterator it = headerValues.iterator(); if (it.hasNext()) { fullResponseBuilder.append(it.next()); while (it.hasNext()) { fullResponseBuilder.append(", ").append(it.next()); } } fullResponseBuilder.append("\n"); });
สุดท้ายเราจะอ่านเนื้อหาตอบกลับเหมือนที่เคยทำก่อนหน้านี้และต่อท้าย
โปรดสังเกตว่าเมธอดgetFullResponseจะตรวจสอบความถูกต้องว่าคำขอนั้นสำเร็จหรือไม่เพื่อที่จะตัดสินใจว่าจำเป็นต้องใช้con.getInputStream ()หรือcon.getErrorStream ()เพื่อดึงเนื้อหาของคำร้องขอ
12. บทสรุป
ในบทความนี้เราได้แสดงวิธีดำเนินการร้องขอ HTTP โดยใช้คลาสHttpUrlConnection
คุณสามารถดูซอร์สโค้ดแบบเต็มของตัวอย่างได้ที่ GitHub