عميل HTTP بلغة Java: إجراء الطلبات بشكل صحيح (المستوى المتقدم)
العمل مع طلبات HTTP هي إحدى المهام الأساسية في تطوير Java الحديث. ومع ذلك، فإن كتابة كود لا يرسل الطلب فحسب، بل يفعل ذلك بشكل موثوق، مع معالجة صحيحة للأخطاء، والمهلات، وإدارة الموارد، يتطلب فهماً عميقاً. في هذه المقالة، سنتجاوز حدود HttpURLConnection البسيط ونتناول التقنيات المتقدمة للعمل مع عملاء HTTP بلغة Java، باستخدام java.net.http.HttpClient المدمج (Java 11+) والمكتبة الشهيرة OkHttp.
1. إدارة المهلات: لا تدع تطبيقك يتجمد
واحدة من أكثر المشاكل شيوعاً عند العمل مع HTTP هي تجميد التطبيق بسبب خادم بطيء أو غير متاح. الإعداد الصحيح للمهلات هو الخطوة الأولى نحو إنشاء عميل متحمل للأخطاء.
أنواع المهلات:
- مهلة الاتصال (Connect Timeout): وقت انتظار إنشاء اتصال TCP بالخادم.
- مهلة القراءة (Read Timeout / Socket Timeout): وقت انتظار البيانات من الخادم بعد إنشاء الاتصال.
- مهلة الكتابة (Write Timeout): وقت انتظار إرسال البيانات إلى الخادم (مناسب لـ POST/PUT).
- مهلة الطلب (Request Timeout): الوقت الإجمالي لتنفيذ طلب HTTP بالكامل (بما في ذلك الاتصال والإرسال واستلام الرد).
مثال على الإعداد لـ java.net.http.HttpClient:
import java.net.http.HttpClient;import java.time.Duration;
public class TimeoutExample { public static HttpClient createClientWithTimeouts() { return HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(5)) // مهلة الاتصال .build(); }
public static void main(String[] args) { HttpClient client = createClientWithTimeouts(); // لمهلات القراءة/الكتابة نستخدم HttpRequest var request = java.net.http.HttpRequest.newBuilder() .uri(java.net.URI.create("https://api.example.com/data")) .timeout(Duration.ofSeconds(10)) // المهلة الإجمالية للطلب .GET() .build(); System.out.println("تم إنشاء العميل مع المهلات: " + client); }}مثال على الإعداد لـ OkHttp:
import okhttp3.OkHttpClient;import java.util.concurrent.TimeUnit;
public class OkHttpTimeoutExample { public static OkHttpClient createOkHttpClient() { return new OkHttpClient.Builder() .connectTimeout(5, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .callTimeout(30, TimeUnit.SECONDS) // المهلة الإجمالية للاستدعاء بالكامل .build(); }
public static void main(String[] args) { OkHttpClient client = createOkHttpClient(); System.out.println("عميل OkHttp مع المهلات جاهز للعمل."); }}2. مجمع الاتصالات وإعادة الاستخدام: توفير الموارد
كل اتصال HTTP جديد يتطلب تكاليف لإنشاء مصافحة TCP وربما مصافحة TLS. بالنسبة للتطبيقات التي ترسل العديد من الطلبات إلى خادم واحد، من الضروري استخدام مجمع اتصالات (connection pool). هذا يسمح بإعادة استخدام الاتصالات الحالية، مما يسرع الطلبات بشكل كبير ويقلل الحمل على الشبكة.
java.net.http.HttpClient يحتوي على مجمع اتصالات مدمج يتم إدارته تلقائياً. ومع ذلك، يمكنك ضبط حجمه:
import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.net.URI;import java.time.Duration;
public class PoolExample { public static void main(String[] args) throws Exception { // HttpClient يدير المجمع بنفسه، لكن يمكننا تقييد