12. تطبيق الويب MVC [person] – الإصدار 7
12.1. مقدمة
في هذا الإصدار، نفترض أنه قد تكون هناك متصفحات عملاء قامت بتعطيل:
- إرسال ملفات تعريف الارتباط من الخادم
- تنفيذ كود JavaScript المضمن في صفحات HTML المعروضة
ومع ذلك، نريد أن يتمكن هذا النوع من المتصفحات من استخدام تطبيقنا. النقطة 2 تعيدنا إلى الإصدار 2 من تطبيقنا، حيث تم إدخال JavaScript بدءًا من الإصدار 3. كان الإصدار 2 يشغل التطبيق بدون JavaScript، لذا تم حل النقطة 2.
قد تكون النقطة 1 صعبة أو غير صعبة في التعامل معها. كان الإصدار 6 من تطبيقنا يعمل بدون ملفات تعريف الارتباط. من خلال دمج الإصدارين 2 و6، نحقق النتيجة المرجوة. سنضيف قيدًا إضافيًا: يجب أن يدير التطبيق جلسة عمل. هذا ليس قيدًا بلا معنى. في تطبيق يتعين على المستخدمين فيه المصادقة، يجب أن يخزن الخادم اسم المستخدم وكلمة المرور الخاصين بالمستخدم لمنعهم من الاضطرار إلى المصادقة في كل صفحة يطلبونها.
حتى الآن، استخدمنا ثلاثة حلول لتخزين المعلومات أثناء التبادلات بين العميل والخادم:
- الجلسة
- ملفات تعريف الارتباط
- الحقول المخفية.
يمكن استبعاد الحل 2 لأن متصفح العميل قد يكون قد عطل ملفات تعريف الارتباط.
الحل 3 هو الحل الوارد في الإصدار 6، والذي درسناه سابقًا. لا يمكن استخدامه لأسباب أمنية. إذا تم تضمين زوج اسم المستخدم/كلمة المرور في كل صفحة يتم إرسالها إلى المتصفح، فهذا يعني أنه ينتقل عبر الشبكة مع كل تبادل بين العميل والخادم. وهذا ليس جيدًا لأمن التطبيق. يمكننا عندئذٍ التفكير في استخدام بروتوكول HTTPS، الذي يقوم بتشفير عمليات التبادل بين العميل والخادم. ومع ذلك، فإن استخدامه لكل صفحة من صفحات التطبيق سيزيد من حمل الخادم.
قد ترغب في استبعاد الحل 1 لأنه يعتمد أيضًا على ملفات تعريف الارتباط. أثناء التبادل الأول بين العميل والخادم، يرسل الخادم إلى العميل رمز جلسة، والذي يرسله العميل بدوره إلى الخادم مع كل طلب جديد. بفضل هذا الرمز، يمكن للخادم التعرف على العميل وتزويده بالمعلومات التي خزنها خلال تبادل سابق. يتم إرسال رمز الجلسة من قبل الخادم في ملف تعريف ارتباط. يمكن للمتصفح الذي لم يتم تعطيل ملفات تعريف الارتباط فيه إرسال ملف تعريف الارتباط هذا إلى الخادم في الطلبات اللاحقة. إذا تم تعطيل ملفات تعريف الارتباط، فهناك حل آخر: يمكن للمتصفح تضمين رمز الجلسة في عنوان URL الذي يطلبه. هذا ما نراه الآن عندما نعيد زيارة ملف [index.jsp] من الإصدار 4:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<c:redirect url="/main"/>
تذكر أن السطر 5 أعلاه يعيد توجيه العميل إلى عنوان URL [/personne4/main?jsessionid=XX]، حيث XX هو رمز الجلسة، كما هو موضح في لقطة الشاشة أدناه التي تم الحصول عليها بعد طلب عنوان URL [http://localhost:8080/personne4]:

دعونا نلقي نظرة فاحصة على كيفية عمل علامة <c:redirect> فيما يتعلق برمز الجلسة. دعونا نستخدم متصفحًا يقبل ملفات تعريف الارتباط. أدناه، نقوم بتكوين متصفح Firefox:

في [1]، نقوم بتمكين ملفات تعريف الارتباط، وفي [2] نقوم بحذف أي ملفات موجودة للبدء من حالة معروفة. ثم نطلب عنوان URL [http://localhost:8080/personne4]. نتلقى الاستجابة التالية:

كان طلب HTTP الأولي للعميل كما يلي:
لاحظ أن العميل لا يرسل ملف تعريف ارتباط للجلسة. استجابة HTTP المرسلة من الخادم هي كما يلي:
- السطر 1: يطلب الخادم من العميل إعادة التوجيه
- السطر 3: يرسل الخادم رمز جلسة مرتبط بسمة [JSESSIONID]
- السطر 4: يحتوي عنوان URL لإعادة التوجيه على رمز الجلسة. وقد وضعته العلامة <c:redirect> هناك لأن العميل لم يرسل ملف تعريف ارتباط للجلسة.
ثم قام المتصفح، الذي طُلب منه إعادة التوجيه، بإرسال الطلب التالي:
- السطر 1: يطلب عنوان URL لإعادة التوجيه، بما في ذلك رمز الجلسة. ولهذا السبب يعرض المتصفح عنوان URL هذا في لقطة الشاشة.
- السطر 10: يرسل المتصفح رمز الجلسة الذي أرسله إليه الخادم في التبادل السابق. هذه هي الطريقة التي تعمل بها ملفات تعريف الارتباط عادةً عندما تكون ممكّنة على متصفح العميل. إذا لم تكن ممكّنة، فلن يتم إرسال ملفات تعريف الارتباط المستلمة.
رد الخادم على هذا الطلب الثاني بما يلي:
لقد عثر على الصفحة المطلوبة ويقوم بإرسالها. لاحظ أنه لم يعد يرسل رمز الجلسة. هكذا تعمل رموز الجلسة عادةً: يرسلها الخادم إلى المتصفح مرة واحدة في شكل ملف تعريف ارتباط، ثم يعيد المتصفح إرسالها مع كل طلب ليتم التعرف عليه.
الآن، باستخدام نفس المتصفح، دعونا نطلب عنوان URL [http://localhost:8080/personne4] مرة أخرى عن طريق كتابته يدويًا. ثم نحصل على الصفحة التالية:

يمكننا أن نرى أن عنوان URL الذي يعرضه المتصفح لم يعد يحتوي على رمز الجلسة. دعونا نلقي نظرة على أول تبادل بين العميل والخادم:
أرسل المتصفح الطلب التالي:
هذا هو بالضبط نفس الطلب السابق، مع اختلاف واحد: في السطر 10، يرسل المتصفح رمز الجلسة الذي تلقّاه خلال التبادل الأول. مرة أخرى، هذا سلوك طبيعي إذا كانت ملفات تعريف الارتباط للمتصفح ممكّنة.
أرسل الخادم الاستجابة التالية:
يُوجه العميل إلى إعادة التوجيه. ونظرًا لأنه تلقى رمز جلسة من العميل، فإنه يواصل الجلسة ولا يرسل رمز جلسة جديدًا. وللسبب نفسه، لا تتضمن علامة <c:redirect> رمز الجلسة هذا في عنوان URL لإعادة التوجيه. وهذا هو السبب في أن عنوان URL الموضح في لقطة الشاشة أعلاه لا يحتوي على رمز جلسة.
النقطة الأساسية المستفادة من كل هذا هي القاعدة التالية: لا تتضمن علامة <c:redirect> رمز الجلسة في عنوان URL لإعادة التوجيه إلا إذا لم يرسل العميل رأس HTTP:
تنطبق هذه القاعدة أيضًا على علامة <c:url>، التي سنستعرضها لاحقًا.
ماذا يحدث مع متصفح تم تعطيل ملفات تعريف الارتباط عليه؟ دعونا نجرب ذلك. أولاً، نقوم بإعادة تعيين المتصفح:

في [1]، نقوم بتعطيل ملفات تعريف الارتباط، وفي [2] نحذف أي ملفات موجودة لنبدأ من حالة معروفة. ثم نطلب عنوان URL [http://localhost:8080/personne4]. نحصل على الاستجابة التالية:

نحصل على نفس النتيجة كما في السابق. ومع ذلك، فإن تبادلات HTTP ليست متطابقة تمامًا:
- الأسطر 1–9: الطلب الأول للمتصفح. لا يرسل ملف تعريف ارتباط للجلسة.
- الأسطر 11-17: استجابة الخادم، التي توجه المتصفح لإعادة التوجيه إلى عنوان URL آخر. وهي ترسل ملف تعريف ارتباط للجلسة. السطر 13: تضمنت علامة <c:redirect> الرمز المميز في عنوان URL لإعادة التوجيه في السطر 14.
- الأسطر 19-27: الطلب الثاني للمتصفح. لا يعيد المتصفح ملف تعريف الارتباط للجلسة الذي أرسله الخادم للتو لأن ملفات تعريف الارتباط الخاصة به معطلة.
- الأسطر 29-33: استجابة الخادم. يمكننا أن نرى أنه على الرغم من أن المتصفح لم يرسل ملف تعريف ارتباط الجلسة، فإن الخادم لا يبدأ جلسة جديدة كما قد يتوقع المرء. ويتضح ذلك من حقيقة أنه لا يرسل رأس HTTP [Set-Cookie] كما فعل في السطر 13. وهذا يعني أنه يواصل الجلسة السابقة. وقد تمكن من استرداد هذه الجلسة بفضل رمز الجلسة الموجود في عنوان URL الذي طلبه المتصفح في السطر 19.
لاحظ أن الخادم يتتبع الجلسة عن طريق استرداد رمز الجلسة الذي أرسله العميل بطريقتين ممكنتين:
- في رأس HTTP [Set-Cookie] المرسل من العميل
- في عنوان URL الذي طلبه العميل
الآن، باستخدام نفس المتصفح، دعونا نطلب عنوان URL [http://localhost:8080/personne4] مرة أخرى عن طريق كتابته يدويًا، تمامًا كما فعلنا عندما كانت ملفات تعريف الارتباط ممكّنة. ثم نحصل على الصفحة التالية:

النتيجة مختلفة عما رأيناه عندما كانت ملفات تعريف الارتباط مسموحة: رمز الجلسة موجود في عنوان URL الذي يعرضه المتصفح. دعونا نوضح هذه النتيجة دون فحص تبادلات HTTP التي حدثت:
[ملفات تعريف الارتباط ممكّنة]
- أثناء الطلب الثاني لعنوان URL [http://localhost:8080/personne4]، أرسل متصفح العميل ملف تعريف الارتباط الخاص بالجلسة الذي تلقّاه من الخادم أثناء الطلب الأول لنفس عنوان URL. وبالتالي، لم تتضمن علامة <c:redirect> رمز الجلسة في عنوان إعادة التوجيه.
[ملفات تعريف الارتباط معطلة]
- أثناء الطلب الثاني لعنوان URL [http://localhost:8080/personne4]، لا يرسل متصفح العميل ملف تعريف الارتباط الخاص بالجلسة الذي تلقّاه من الخادم أثناء الطلب الأول لنفس عنوان URL، نظرًا لأن ملفات تعريف الارتباط لديه معطلة. وبالتالي، تتضمن علامة <c:redirect> رمز الجلسة في عنوان URL الخاص بإعادة التوجيه. وهذا هو سبب ظهوره في لقطة الشاشة أعلاه.
تسمح لك علامتا <c:redirect> و <c:url> بتضمين رمز الجلسة في عناوين URL. وهذا هو الحل المقترح هنا.
12.2. مشروع Eclipse
لإنشاء مشروع Eclipse [mvc-personne-07] لتطبيق الويب [/personne7]، قم بنسخ المشروع [mvc-personne-06] باتباع الإجراء الموضح في القسم 6.2.
![]() | ![]() |
12.3. تكوين تطبيق الويب [personne7]
فيما يلي ملف web.xml الخاص بتطبيق /personne7:
<?xml version="1.0" encoding="UTF-8"?>
...
<display-name>mvc-personne-07</display-name>
...
هذا الملف مطابق للملف الموجود في الإصدار السابق باستثناء السطر 3، حيث تغير اسم العرض لتطبيق الويب إلى [mvc-personne-07]. وتبقى الصفحة الرئيسية [index.jsp] دون تغيير.
...
<c:redirect url="/do/formulaire"/>
12.4. كود العرض
تعود طرق العرض [form، response، errors] إلى ما كانت عليه في الإصدار 2، أي بدون JavaScript. ومع ذلك، فإنها تحتفظ بعلامات JSTL من أحدث الإصدارات.
12.4.1. عرض [form]

تمت إزالة الأزرار المرتبطة برمز JavaScript.
[form.jsp]:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne - formulaire</title>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form name="frmPersonne" action="<c:url value="validationFormulaire"/>" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="${nom}" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="${age}" type="text" size="3"></td>
</tr>
<tr>
</table>
<table>
<tr>
<td><input type="submit" name="bouton" value="Envoyer"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="submit" name="bouton" value="Effacer"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
- السطر 14: يتم كتابة عنوان URL الهدف لـ POST باستخدام العلامة <c:url> بحيث يتم تضمين رمز الجلسة في حالة ما إذا كان العميل متصفحًا لا يرسل رأس HTTP [Cookie].
- يحتوي النموذج على زرين [submit]: [Submit] (السطر 28) و [Clear] (السطر 30). كلا الزرين لهما نفس الاسم: button. عند تشغيل POST، سيرسل المتصفح المعلمة:
- button=Submit إذا تم تشغيل POST بواسطة زر [Submit]
- button=Clear إذا تم تشغيل POST بواسطة زر [Clear]
ستساعدنا هذه المعلمة في تحديد الإجراء المحدد الذي يجب اتخاذه، حيث إن عنوان URL [/do/validationFormulaire] يتوافق الآن مع إجراءين مختلفين.
12.4.2. طريقة العرض [response]

[response.jsp]:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Personne - réponse</h2>
<hr>
<table>
<tr>
<td>Nom</td>
<td>${nom}</td>
</tr>
<tr>
<td>Age</td>
<td>${age}</td>
</tr>
</table>
<br>
<a href="<c:url value="retourFormulaire"/>">${lienRetourFormulaire}</a>
</body>
</html>
- السطر 24: يتم كتابة عنوان URL الهدف لـ HREF باستخدام العلامة <c:url> بحيث يتم تضمين رمز الجلسة في حالة ما إذا كان العميل متصفحًا لا يرسل رأس HTTP [Cookie].
12.4.3. عرض [errors]

[errors.jsp]:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Les erreurs suivantes se sont produites</h2>
<ul>
<c:forEach var="erreur" items="${erreurs}">
<li>${erreur}</li>
</c:forEach>
</ul>
<br>
<a href="<c:url value="retourFormulaire"/>">${lienRetourFormulaire}</a>
</body>
</html>
- السطر 18: يتم كتابة عنوان URL الهدف لـ HREF باستخدام العلامة <c:url> بحيث يتم تضمين رمز الجلسة في حالة ما إذا كان العميل متصفحًا لا يرسل رأس HTTP [Cookie].
ندعو القراء إلى اختبار هذه العروض الجديدة باستخدام نفس النهج المتبع في الإصدارات السابقة.
12.5. وحدة التحكم [ServletPersonne]
وحدة التحكم [ServletPersonne] لتطبيق الويب [/personne7] هي كما يلي:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | |
- السطر 35: يتم تنفيذ الإجراء [/retourFormulaire] عبر طلب GET بدلاً من طلب POST كما في الإصدار السابق.
- الأسطر 70–87: يتم تشغيل الإجراء [/validationFormulaire] بواسطة طلب POST ناتج عن النقر على أحد الزرين [Envoyer] أو [Effacer] في عرض [form]. تتعامل الطريقة [doValidationFormulaire] مع هاتين الحالتين باستخدام طريقتين مختلفتين.
- الأسطر 90–103: تتوافق طريقة [doEnvoyer] مع طريقة [doValidationFormulaire] من الإصدار السابق. يتم تخزين البيانات المدخلة في الجلسة (الأسطر 96–98)، بينما في الإصدار السابق كانت توضع في الطلب.
- الأسطر 58–67: يجب أن تعرض الطريقة الجديدة [doEffacer] نموذجًا فارغًا. يمكننا استدعاء الطريقة [doInit]، التي تؤدي هذه المهمة بالفعل. هنا، ننتهز الفرصة لمسح عناصر [name, age] من الجلسة أيضًا حتى تستمر في عكس أحدث حالة للنموذج.
- الأسطر 50-55: نطلب عرض طريقة العرض [form] دون أي تهيئة واضحة لنموذج طريقة العرض. يتكون هذا النموذج في الواقع من عناصر [name, age] الموجودة بالفعل في الجلسة. لا يلزم اتخاذ أي إجراء آخر.
12.6. الاختبارات
ابدأ أو أعد تشغيل Tomcat بعد دمج مشروع Eclipse [personne-mvc-07] فيه، ثم اطلب عنوان URL [http://localhost:8080/personne7] باستخدام متصفح مع تعطيل ملفات تعريف الارتباط وحذف ملفات تعريف الارتباط الموجودة. يتم الحصول على الاستجابة التالية:

فيما يلي شفرة المصدر التي يتلقاها المتصفح:
السطر 1: رمز الجلسة موجود في عنوان URL الهدف لـ POST.
دعونا نملأ النموذج ونرسله:

فيما يلي شفرة المصدر التي يتلقاها المتصفح:
السطر 3: رمز الجلسة موجود في عنوان URL الهدف للرابط.

