مقدمة إلى خدمات REST
رسالة مهمة للطلاب
انتباه: هذا الفصل هو مراجعة اختيارية.
يُقدم هذا الفصل كموارد إضافية لأولئك الذين يرغبون في تعميق فهمهم لخدمات الويب REST. على الرغم من أن هذا المحتوى ليس إلزاميًا للدورة، إلا أنه يمكن أن يكون مفيدًا لـ:
- الطلاب الذين لديهم فجوات في مفاهيم خدمات الويب
- أولئك الذين يرغبون في مراجعة شاملة قبل البدء في Spring Boot
- الأشخاص الذين يريدون فهم الأسس النظرية لـ REST
إذا كنت بالفعل مرتاحًا مع خدمات الويب REST، يمكنك الانتقال مباشرة إلى الوحدة التالية.
محتوى الفصل
تتضمن هذه القسم أربع أجزاء:
- الجزء 1: مقدمة عن REST - مقدمة إلى بنية REST، المبادئ الرئيسية والمفاهيم عديمة الحالة مقابل ذات الحالة
- الجزء 2: طرق HTTP - تفاصيل حول طرق HTTP في REST وأمثلة على الاستخدام مع Java
- الجزء 3: أمثلة عملية - استخدام طرق GET، POST، PUT و DELETE مع كود Java
- الجزء 4: إدارة الأخطاء - رموز حالة HTTP وإدارة الأخطاء في APIs REST
الجزء 1: مقدمة عن REST
REST (نقل الحالة التمثيلية) هو بنية برمجية مصممة لإنشاء خدمات ويب قابلة للتوسع وعالية الأداء. تم تقديمها في عام 2000 بواسطة Roy T. Fielding، أحد المبدعين الرئيسيين لبروتوكول HTTP. REST مبنية على مجموعة من القيود التي تجعل الأنظمة الموزعة أبسط وأكثر كفاءة.
المبادئ الرئيسية لـ REST
1. توحيد الواجهة
يتم توحيد التفاعلات بين العميل والخادم باستخدام طرق HTTP، وURI لتحديد الموارد، وصيغ تمثيل قياسية مثل JSON أو XML. هذا يسمح بتواصل واضح ومتسق.
2. عديمة الحالة
لا يحتفظ الخادم بأي معلومات حول حالة الجلسات بين الطلبات. يجب أن تحتوي كل طلب من العميل على جميع المعلومات اللازمة لمعالجة الطلب. هذا يبسط إدارة الجلسات.
3. قابلة للتخزين المؤقت
يمكن تخزين استجابات الخادم مؤقتًا لتحسين الأداء. يتم تحديد توجيهات التخزين المؤقت في رؤوس HTTP، مما يسمح بتقليل أوقات الاستجابة وحمل الخادم.
4. عميل-خادم
هناك فصل في المسؤوليات بين العميل (الذي يدير واجهة المستخدم) والخادم (الذي يدير تخزين البيانات والمنطق التجاري). هذا يسهل التطوير المستقل لواجهة المستخدم والخلفية.
5. نظام متعدد الطبقات
يمكن بناء بنية REST في طبقات، مما يحسن من مرونة وقابلية توسع النظام. على سبيل المثال، يمكن لطبقة أن تدير المصادقة، بينما تتولى أخرى تخزين البيانات.
عديمة الحالة مقابل ذات الحالة
بنية عديمة الحالة
في REST، البنية هي عديمة الحالة. هذا يعني أن كل طلب يرسله العميل إلى الخادم يجب أن يحتوي على جميع المعلومات اللازمة لمعالجة الطلب. لا يحتفظ الخادم بمعلومات حول حالة التفاعلات السابقة، مما يبسط إدارة النظام.
مثال:
GET /api/users/123 HTTP/1.1
Host: example.com
Authorization: Bearer <token>
في هذا المثال، يرسل العميل جميع المعلومات اللازمة لمصادقة الطلب (عبر الرأس Authorization) وتحديد المورد المطلوب (/api/users/123).
بنية ذات الحالة
على النقيض، في بنية ذات الحالة، يحتفظ الخادم بحالة الجلسة بين الطلبات. هذا يمكن أن يعقد إدارة الجلسات ويجعل النظام أقل مرونة وأقل قابلية للتوسع.
طرق HTTP في REST
طرق HTTP هي أفعال تشير إلى الإجراء الذي يجب تنفيذه على مورد محدد بواسطة URI (معرف الموارد الموحد). فيما يلي الطرق الأكثر استخدامًا في REST.
جدول طرق HTTP
+-------------+---------------------+---------------------------------------------------------+
| Méthode | Description | Exemples de Code |
+-------------+---------------------+---------------------------------------------------------+
| GET | استرجاع مورد | GET /api/users/123 HTTP/1.1 |
| | | Host: example.com |
+-------------+---------------------+---------------------------------------------------------+
| POST | إنشاء مورد | POST /api/users HTTP/1.1 |
| | | Host: example.com |
| | | Content-Type: application/json |
| | | |
| | | { |
| | | "name": "John Doe", |
| | | "email": "john@example.com" |
| | | } |
+-------------+---------------------+---------------------------------------------------------+
| PUT | استبدال مورد كامل | PUT /api/users/123 HTTP/1.1 |
| | | Host: example.com |
| | | Content-Type: application/json |
+-------------+---------------------+---------------------------------------------------------+
| PATCH | تعديل جزئي لمورد | PATCH /api/users/123 HTTP/1.1 |
| | | Host: example.com |
| | | Content-Type: application/json |
+-------------+---------------------+---------------------------------------------------------+
| DELETE | حذف مورد | DELETE /api/users/123 HTTP/1.1 |
| | | Host: example.com |
+-------------+---------------------+---------------------------------------------------------+
طرق أقل استخدامًا
+-------------+---------------------+---------------------------------------------------------+
| OPTIONS | تحديد الطرق التي | OPTIONS /api/users HTTP/1.1 |
| | يمكن للخادم معالجتها| Host: example.com |
| | | |
| | | Réponse : |
| | | HTTP/1.1 200 OK |
| | | Allow: GET, POST, OPTIONS |
+-------------+---------------------+---------------------------------------------------------+
| HEAD | استرجاع رؤوس مورد | HEAD /api/users/123 HTTP/1.1 |
| | بدون جسم استجابة | Host: example.com |
| | | |
| | | Réponse : |
| | | HTTP/1.1 200 OK |
| | | Content-Type: application/json |
+-------------+---------------------+---------------------------------------------------------+
رؤوس HTTP
رؤوس HTTP هي عناصر مهمة توفر معلومات إضافية حول البيانات المرسلة أثناء الطلبات والاستجابات HTTP.
جدول رؤوس HTTP
+-------------------+----------------------------------+------------------------------------------------+
| En-Tête | Description | Exemple de Code |
+-------------------+----------------------------------+------------------------------------------------+
| Content-Type | يحدد نوع محتوى المورد | Content-Type: application/json |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
| Accept | يشير إلى أنواع المحتوى التي | Accept: application/json |
| | يقبلها العميل | |
+-------------------+----------------------------------+------------------------------------------------+
| Authorization | يوفر معلومات المصادقة | Authorization: Bearer <token> |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
| Cache-Control | يحدد توجيهات التخزين المؤقت | Cache-Control: no-cache |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
| Content-Length | يحدد حجم جسم الاستجابة | Content-Length: 348 |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
| Location | يشير إلى موقع مورد تم إنشاؤه | Location: http://example.com/api/users/123 |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
إدارة رموز HTTP
تُستخدم رموز حالة HTTP للإشارة إلى نتيجة طلب HTTP.
جدول رموز حالة HTTP
+-------------------+----------------------------------+------------------------------------------------+
| Code HTTP | Signification | Exemple de Scénario |
+-------------------+----------------------------------+------------------------------------------------+
| 200 OK | الطلب نجح | استجابة لطلب GET لاسترجاع مورد |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
| 201 Created | تم إنشاء مورد جديد | استجابة لطلب POST لإنشاء مستخدم جديد |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
| 204 No Content | الطلب نجح ولكن لا يوجد محتوى | استجابة لطلب DELETE بعد حذف مورد |
| | لإرجاعه | |
+-------------------+----------------------------------+------------------------------------------------+
| 400 Bad Request | الطلب غير صحيح أو يحتوي على | العميل يرسل طلبًا ببيانات غير صالحة |
| | أخطاء | |
+-------------------+----------------------------------+------------------------------------------------+
| 401 Unauthorized | المصادقة مطلوبة | العميل يحاول الوصول إلى مورد دون تقديم رمز |
| | | مصادقة |
+-------------------+----------------------------------+------------------------------------------------+
| 403 Forbidden | الوصول ممنوع | العميل ليس لديه الإذن اللازم للوصول إلى المورد |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
| 404 Not Found | لم يتم العثور على المورد | العميل يحاول الوصول إلى مورد غير موجود |
| | | |
+-------------------+----------------------------------+------------------------------------------------+
| 500 Internal | حدث خطأ داخلي في الخادم | حدث استثناء غير متوقع على الخادم أثناء معالجة |
| Server Error | | الطلب |
+-------------------+----------------------------------+------------------------------------------------+
الجزء 2: طرق HTTP بالتفصيل
في بنية REST، تحدد طرق HTTP الإجراء الذي يرغب العميل في تنفيذه على مورد.
جدول ملخص
| Méthode | Description | Usage typique |
|---|---|---|
GET | يسترجع موردًا دون تعديل حالته | قراءة صفحة ويب، استرجاع بيانات |
POST | يرسل بيانات لإنشاء مورد جديد | إرسال نموذج، إضافة إدخال جديد |
PUT | يحدث موردًا بإرسال النسخة الكاملة | استبدال أو إنشاء مورد |
PATCH | يحدث موردًا جزئيًا | تعديل جزئي لمورد موجود |
DELETE | يحذف موردًا محددًا | حذف إدخال، ملف |
HEAD | يسترجع رؤوس مورد، مشابه لـ GET، بدون الجسم | التحقق من آخر تعديل |
OPTIONS | يستفسر الخادم عن الطرق المتاحة | تحضير طلب، اكتشاف الطرق |
الجزء 3: أمثلة عملية مع Java
مثال GET: استرجاع مورد
@GET
@Path("/testGet")
public Response getTestResource() {
// Logique de récupération de la ressource
return Response.ok("تم استرجاع المورد بنجاح").build();
}
التفاصيل:
- @GET: تشير هذه التعليمة إلى أن الطريقة ستستجيب لطلب HTTP GET
- @Path("/testGet"): تحدد عنوان URL النسبي لهذه الطريقة
- Response.ok(): ينشئ استجابة HTTP برمز 200 (OK)
الاستخدام النموذجي: عرض معلومات للمستخدم (تفاصيل مستخدم، منتج، إلخ)
مثال POST: إنشاء مورد جديد
@POST
@Path("/testPost")
@Consumes(MediaType.APPLICATION_JSON)
public Response createTestResource(String json) {
// Logique pour créer une ressource à partir du JSON reçu
return Response.status(Response.Status.CREATED).entity("تم إنشاء المورد").build();
}
التفاصيل:
- @POST: تشير هذه التعليمة إلى أن الطريقة ستستجيب لطلب HTTP POST
- @Consumes(MediaType.APPLICATION_JSON): تشير إلى أن الطريقة تتوقع بيانات بصيغة JSON
- Response.Status.CREATED: رمز 201 يشير إلى أنه تم إنشاء مورد جديد
الاستخدام النموذجي: تسجيل مستخدم جديد، إنشاء منتج جديد
مثال PUT: تحديث مورد
@PUT
@Path("/testPut/{id}")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateTestResource(@PathParam("id") String id, String json) {
// Logique pour mettre à jour la ressource identifiée par id
return Response.ok("تم تحديث المورد").build();
}
التفاصيل:
- @PUT: تشير هذه التعليمة إلى أن الطريقة ستستجيب لطلب HTTP PUT
- @PathParam("id"): استخراج معرف المورد من عنوان URL
- Response.ok(): رمز 200 للإشارة إلى أن التحديث نجح
الاستخدام النموذجي: تعديل تفاصيل منتج، تحديث ملف تعريف مستخدم
مثال DELETE: حذف مورد
@DELETE
@Path("/testDelete/{id}")
public Response deleteTestResource(@PathParam("id") String id) {
// Logique pour supprimer la ressource identifiée par id
return Response.status(Response.Status.NO_CONTENT).build();
}
التفاصيل:
- @DELETE: تشير هذه التعليمة إلى أن الطريقة ستستجيب لطلب HTTP DELETE
- Response.Status.NO_CONTENT: رمز 204 يشير إلى أنه تم حذف مورد بدون محتوى لإرجاعه
الاستخدام النموذجي: حذف مستخدم، منتج، تعليق
الجزء 4: إدارة الأخطاء
الإدارة المناسبة للأخطاء ضرورية في APIs REST. إليك كيفية إعادة رموز الحالة الأكثر استخدامًا.
رمز 200 OK
يشير الرمز 200 OK إلى أن الطلب تمت معالجته بنجاح.
@GET
@Path("/testGet")
public Response getTestResource() {
return Response.ok("تم استرجاع المورد بنجاح").build();
}
رمز 301 Moved Permanently
يشير الرمز 301 Moved Permanently إلى أن المورد قد تم نقله بشكل دائم.
@GET
@Path("/oldPath")
public Response redirectResource() {
return Response.status(Response.Status.MOVED_PERMANENTLY)
.location(URI.create("/newPath"))
.build();
}
رمز 400 Bad Request
يشير الرمز 400 Bad Request إلى أن الخادم لا يمكنه معالجة الطلب بسبب خطأ من العميل.
@POST
@Path("/testPost")
@Consumes(MediaType.APPLICATION_JSON)
public Response createTestResource(String json) {
if (json == null || json.isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("بيانات غير صالحة: جسم الطلب فارغ.")
.build();
}
return Response.status(Response.Status.CREATED)
.entity("تم إنشاء المورد")
.build();
}
رمز 404 Not Found
يتم إعادة الرمز 404 Not Found عندما لا يوجد المورد المطلوب.
@GET
@Path("/testGet/{id}")
public Response getTestResource(@PathParam("id") String id) {
boolean resourceExists = false;
if (!resourceExists) {
return Response.status(Response.Status.NOT_FOUND)
.entity("لم يتم العثور على المورد للمعرف: " + id)
.build();
}
return Response.ok("تم العثور على المورد").build();
}
رمز 500 Internal Server Error
يشير الرمز 500 Internal Server Error إلى أن خطأ غير متوقع حدث على الخادم.
@GET
@Path("/testGet/{id}")
public Response getTestResource(@PathParam("id") String id) {
try {
String resource = retrieveResource(id);
return Response.ok(resource).build();
} catch (Exception e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("خطأ داخلي في الخادم: " + e.getMessage())
.build();
}
}
توصيات لإدارة الأخطاء
- استخدم رموز HTTP المناسبة: كل رمز له معنى محدد ويسمح للعميل بفهم نتيجة طلبه
- قدم رسائل خطأ واضحة: قم بتضمين رسالة خطأ توضيحية في جسم الاستجابة
- اعتبر الأمان: لا تكشف عن الكثير من التفاصيل التقنية لتجنب تقديم معلومات قابلة للاستغلال
الخاتمة
يوفر هذا الفصل أساسًا قويًا لفهم والتفاعل مع APIs RESTful. هذه المفاهيم أساسية للعمل مع Spring Boot، الذي يبسط بشكل كبير إنشاء APIs REST بفضل تعليمه التوضيحية وتكوينه التلقائي.
في الوحدات التالية، سترى كيف يسهل Spring Boot تنفيذ هذه المفاهيم REST بطريقة أنيقة وفعالة.