java.net.http.HttpClient
إرسال طلبات متزامنة
java.net.http.HttpClient درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
عميل HTTP الحديث
منذ Java 11، توفّر JDK عميل HTTP حديثًا ضمن الحزمة java.net.http. وهو يستبدل HttpURLConnection القديم بواجهة API واضحة وسلسة تدعم HTTP/1.1 وHTTP/2.
الأنواع الأساسية الثلاثة هي:
- HttpClient — يرسل الطلبات ويدير الإعدادات (المهل الزمنية، والوكلاء، وإعادة التوجيه).
- HttpRequest — وصف غير قابل للتغيير لما يجب إرساله.
- HttpResponse — النتيجة، بما في ذلك رمز الحالة والرؤوس والنص.
إنشاء HttpClient
تنشئ عميلًا باستخدام الأسلوب الساكن newBuilder(). ويمكن إعادة استخدام عميل واحد لطلبات عديدة، وهو آمن للاستخدام مع مؤشرات ترابط متعددة.
نضبط هنا HTTP/2 ومهلة الاتصال. ويتوفر newHttpClient() أيضًا لإنشاء مثيل افتراضي سريع.
import java.net.http.HttpClient;
import java.time.Duration;
public class Main {
public static void main(String[] args) {
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
System.out.println("Client version: " + client.version());
}
}إنشاء طلب
HttpRequest غير قابل للتغيير ويتم إنشاؤه باستخدام fluent builder. يلزمك، في الحد الأدنى، توفير URI؛ وينفّذ الطلب GET افتراضيًا.
يمكنك تحويل سلسلة نصية إلى URI باستخدام URI.create(...).
import java.net.URI;
import java.net.http.HttpRequest;
public class Main {
public static void main(String[] args) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/data"))
.GET()
.build();
System.out.println("Method: " + request.method());
System.out.println("URI: " + request.uri());
}
}الإرسال بشكل متزامن
تحجب الدالة send مؤشر الترابط المستدعي حتى وصول الاستجابة. وهي تحتاج إلى BodyHandler يحدد للعميل كيفية تفسير نص الاستجابة.
تقرأ BodyHandlers.ofString() النص إلى كائن من النوع String.
import java.net.URI;
import java.net.http.*;
public class Main {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
}
}قراءة رمز الحالة
توفّر الاستجابة الدالة statusCode() التي تعيد قيمة من النوع int. تشير الرموز ضمن النطاق 2xx إلى النجاح، بينما تشير 3xx إلى عمليات إعادة التوجيه، و4xx إلى أخطاء العميل، و5xx إلى أخطاء الخادم.
ملاحظة: لا يرمي عميل HTTP استثناءً عند تلقي استجابة 4xx أو 5xx — بل يجب عليك التحقق من الرمز بنفسك.
public class Main {
public static void main(String[] args) {
int status = 404;
String label;
if (status >= 200 && status < 300) label = "Success";
else if (status >= 300 && status < 400) label = "Redirect";
else if (status >= 400 && status < 500) label = "Client error";
else label = "Server error";
System.out.println(status + " -> " + label);
}
}قراءة النص
باستخدام BodyHandlers.ofString()، تعيد response.body() قيمة من النوع String. توجد معالجات أخرى للبايتات والملفات والتدفقات، وسنتناولها لاحقًا.
يحاكي هذا المقتطف محتوى النص الذي ستتلقاه.
public class Main {
public static void main(String[] args) {
String body = "{\"message\":\"hello\"}";
System.out.println("Body length: " + body.length());
System.out.println("Body: " + body);
}
}معالجة عمليات إعادة التوجيه
لا يتبع العميل عمليات إعادة التوجيه افتراضيًا. يمكنك ضبط ذلك في builder باستخدام followRedirects(...).
الخيارات في HttpClient.Redirect هي NEVER وALWAYS وNORMAL، حيث يتبع الأخير عمليات إعادة التوجيه باستثناء الانتقال من HTTPS إلى HTTP.
import java.net.http.HttpClient;
public class Main {
public static void main(String[] args) {
HttpClient client = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
System.out.println("Redirect policy: " + client.followRedirects());
}
}مهلات الطلبات
تُضبط مهلة الاتصال على مستوى العميل. أما مهلة الطلب، أي المدة التي ينتظرها العميل وصول الاستجابة، فتُضبط على الطلب باستخدام timeout(...).
إذا انتهت المهلة، ترمي send استثناءً من النوع HttpTimeoutException.
import java.net.URI;
import java.net.http.HttpRequest;
import java.time.Duration;
public class Main {
public static void main(String[] args) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.timeout(Duration.ofSeconds(5))
.build();
System.out.println("Timeout set: " + request.timeout().isPresent());
}
}فحص ترويسات الاستجابة
تحتوي الاستجابة على كائن من النوع HttpHeaders يمكن الوصول إليه عبر headers(). لا تميّز عمليات البحث في الترويسات بين حالة الأحرف، وقد تعيد قيمًا متعددة؛ لذلك تعيد firstValue(...) قيمة من النوع Optional<String>.
import java.util.Optional;
public class Main {
public static void main(String[] args) {
// Simulating a header lookup result
Optional<String> contentType = Optional.of("application/json");
System.out.println("Content-Type: " + contentType.orElse("unknown"));
}
}الاستثناءات المُتحقَّق منها
تُصرّح send المتزامنة باستثناءين مُتحقَّق منهما:
- IOException — فشل في الشبكة أو البروتوكول.
- InterruptedException — تمت مقاطعة مؤشر الترابط المحجوب.
يجب عليك التقاط الاستثناءين أو التصريح بهما. أما الاستدعاءات غير المتزامنة، في الدرس التالي، فتتجنب ذلك بإرجاع future.
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
// client.send(...) would go here
throw new IOException("connection refused");
} catch (IOException e) {
System.out.println("Network problem: " + e.getMessage());
}
}
}عميل قابل لإعادة الاستخدام
أفضل ممارسة هي إنشاء واحد من HttpClient وإعادة استخدامه في أنحاء التطبيق. فهو يجمع الاتصالات في مجموعة، وآمن تمامًا للاستخدام مع مؤشرات الترابط.
يؤدي إنشاء عميل جديد لكل طلب إلى هدر الموارد وإلغاء فائدة تعدد الإرسال في HTTP/2.
import java.net.http.HttpClient;
public class Main {
private static final HttpClient SHARED = HttpClient.newHttpClient();
public static void main(String[] args) {
System.out.println("Shared client ready: " + (SHARED != null));
}
}تحقق سريع
اختبر مدى فهمك لعميل HTTP المتزامن.
مراجعة
لقد تعلمت أساسيات عميل HTTP في JDK:
- HttpClient.newBuilder() يضبط الإصدار والمهلة وعمليات إعادة التوجيه؛ أعد استخدام مثيل واحد.
- HttpRequest.newBuilder().uri(...).GET() ينشئ طلبًا غير قابل للتغيير.
- client.send(request, BodyHandlers.ofString()) يحجب مؤشر الترابط ويعيد
HttpResponse<String>. - اقرأ النتائج باستخدام
statusCode()وbody()وheaders(). - لا تؤدي الرموز غير 2xx إلى رمي استثناء — تحقّق منها بنفسك.
الأسئلة الشائعة
هل درس «java.net.http.HttpClient» مجاني؟
نعم — نص درس «java.net.http.HttpClient» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «java.net.http.HttpClient»؟
إرسال طلبات متزامنة تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «java.net.http.HttpClient»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- java.net.http.HttpClient
- الطلبات غير المتزامنة
- أجسام الطلبات والترويسات
- معالجة الاستجابات