Skip to content

12. تطبيق الويب MVC [person] – الإصدار 7

12.1. مقدمة

في هذا الإصدار، نفترض أنه قد تكون هناك متصفحات عملاء قامت بتعطيل:

  1. إرسال ملفات تعريف الارتباط من الخادم
  2. تنفيذ كود JavaScript المضمن في صفحات HTML المعروضة

ومع ذلك، نريد أن يتمكن هذا النوع من المتصفحات من استخدام تطبيقنا. النقطة 2 تعيدنا إلى الإصدار 2 من تطبيقنا، حيث تم إدخال JavaScript بدءًا من الإصدار 3. كان الإصدار 2 يشغل التطبيق بدون JavaScript، لذا تم حل النقطة 2.

قد تكون النقطة 1 صعبة أو غير صعبة في التعامل معها. كان الإصدار 6 من تطبيقنا يعمل بدون ملفات تعريف الارتباط. من خلال دمج الإصدارين 2 و6، نحقق النتيجة المرجوة. سنضيف قيدًا إضافيًا: يجب أن يدير التطبيق جلسة عمل. هذا ليس قيدًا بلا معنى. في تطبيق يتعين على المستخدمين فيه المصادقة، يجب أن يخزن الخادم اسم المستخدم وكلمة المرور الخاصين بالمستخدم لمنعهم من الاضطرار إلى المصادقة في كل صفحة يطلبونها.

حتى الآن، استخدمنا ثلاثة حلول لتخزين المعلومات أثناء التبادلات بين العميل والخادم:

  1. الجلسة
  2. ملفات تعريف الارتباط
  3. الحقول المخفية.

يمكن استبعاد الحل 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]:

Image

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

Image

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

Image

كان طلب HTTP الأولي للعميل كما يلي:

1
2
3
4
5
6
7
8
9
GET /personne4/ HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

لاحظ أن العميل لا يرسل ملف تعريف ارتباط للجلسة. استجابة HTTP المرسلة من الخادم هي كما يلي:

1
2
3
4
5
6
7
HTTP/1.x 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=1ACA010A6BA28FB9E30A1D3184F574BC; Path=/personne4
Location: http://localhost:8080/personne4/main;jsessionid=1ACA010A6BA28FB9E30A1D3184F574BC
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 0
Date: Tue, 23 May 2006 09:10:05 GMT
  • السطر 1: يطلب الخادم من العميل إعادة التوجيه
  • السطر 3: يرسل الخادم رمز جلسة مرتبط بسمة [JSESSIONID]
  • السطر 4: يحتوي عنوان URL لإعادة التوجيه على رمز الجلسة. وقد وضعته العلامة <c:redirect> هناك لأن العميل لم يرسل ملف تعريف ارتباط للجلسة.

ثم قام المتصفح، الذي طُلب منه إعادة التوجيه، بإرسال الطلب التالي:

GET /personne4/main;jsessionid=1ACA010A6BA28FB9E30A1D3184F574BC HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: JSESSIONID=1ACA010A6BA28FB9E30A1D3184F574BC
  • السطر 1: يطلب عنوان URL لإعادة التوجيه، بما في ذلك رمز الجلسة. ولهذا السبب يعرض المتصفح عنوان URL هذا في لقطة الشاشة.
  • السطر 10: يرسل المتصفح رمز الجلسة الذي أرسله إليه الخادم في التبادل السابق. هذه هي الطريقة التي تعمل بها ملفات تعريف الارتباط عادةً عندما تكون ممكّنة على متصفح العميل. إذا لم تكن ممكّنة، فلن يتم إرسال ملفات تعريف الارتباط المستلمة.

رد الخادم على هذا الطلب الثاني بما يلي:

1
2
3
4
5
HTTP/1.x 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 2376
Date: Tue, 23 May 2006 09:10:05 GMT

لقد عثر على الصفحة المطلوبة ويقوم بإرسالها. لاحظ أنه لم يعد يرسل رمز الجلسة. هكذا تعمل رموز الجلسة عادةً: يرسلها الخادم إلى المتصفح مرة واحدة في شكل ملف تعريف ارتباط، ثم يعيد المتصفح إرسالها مع كل طلب ليتم التعرف عليه.

الآن، باستخدام نفس المتصفح، دعونا نطلب عنوان URL [http://localhost:8080/personne4] مرة أخرى عن طريق كتابته يدويًا. ثم نحصل على الصفحة التالية:

Image

يمكننا أن نرى أن عنوان URL الذي يعرضه المتصفح لم يعد يحتوي على رمز الجلسة. دعونا نلقي نظرة على أول تبادل بين العميل والخادم:

أرسل المتصفح الطلب التالي:

GET /personne4 HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: JSESSIONID=1ACA010A6BA28FB9E30A1D3184F574BC

هذا هو بالضبط نفس الطلب السابق، مع اختلاف واحد: في السطر 10، يرسل المتصفح رمز الجلسة الذي تلقّاه خلال التبادل الأول. مرة أخرى، هذا سلوك طبيعي إذا كانت ملفات تعريف الارتباط للمتصفح ممكّنة.

أرسل الخادم الاستجابة التالية:

1
2
3
4
5
HTTP/1.x 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Location: http://localhost:8080/personne4/
Transfer-Encoding: chunked
Date: Tue, 23 May 2006 09:24:39 GMT

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

النقطة الأساسية المستفادة من كل هذا هي القاعدة التالية: لا تتضمن علامة <c:redirect> رمز الجلسة في عنوان URL لإعادة التوجيه إلا إذا لم يرسل العميل رأس HTTP:

Cookie: JSESSIONID=1ACA010A6BA28FB9E30A1D3184F574BC

تنطبق هذه القاعدة أيضًا على علامة <c:url>، التي سنستعرضها لاحقًا.

ماذا يحدث مع متصفح تم تعطيل ملفات تعريف الارتباط عليه؟ دعونا نجرب ذلك. أولاً، نقوم بإعادة تعيين المتصفح:

Image

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

Image

نحصل على نفس النتيجة كما في السابق. ومع ذلك، فإن تبادلات HTTP ليست متطابقة تمامًا:

GET /personne4/ HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

HTTP/1.x 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=911B8156E0A9D32C2D256020C898E05C; Path=/personne4
Location: http://localhost:8080/personne4/main;jsessionid=911B8156E0A9D32C2D256020C898E05C
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 0
Date: Tue, 23 May 2006 09:39:55 GMT

GET /personne4/main;jsessionid=911B8156E0A9D32C2D256020C898E05C HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

HTTP/1.x 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 2376
Date: Tue, 23 May 2006 09:39:55 GMT
  • الأسطر 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] مرة أخرى عن طريق كتابته يدويًا، تمامًا كما فعلنا عندما كانت ملفات تعريف الارتباط ممكّنة. ثم نحصل على الصفحة التالية:

Image

النتيجة مختلفة عما رأيناه عندما كانت ملفات تعريف الارتباط مسموحة: رمز الجلسة موجود في عنوان 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]

Image

تمت إزالة الأزرار المرتبطة برمز 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]

Image

[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]

Image

[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] هي كما يلي:

package istia.st.servlets.personne;

...

@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
    // instance parameters
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse","lienRetourFormulaire"};
    private Map params=new HashMap<String,String>();

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
    }

    // GET
    @SuppressWarnings("unchecked")
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

...
        // retrieve the request sending method
        String méthode=request.getMethod().toLowerCase();
        // retrieve the action to be executed
        String action=request.getPathInfo();
...
        if(méthode.equals("post") && action.equals("/validationFormulaire")){
            // validation of input form
            doValidationFormulaire(request,response);
            return;
        }
        if(méthode.equals("get") && action.equals("/retourFormulaire")){
            // back to input form
            doRetourFormulaire(request,response);
            return;
        }
        // other cases
        doInit(request,response);
    }

    // empty form display
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
...
    }

    // display pre-filled form
    void doRetourFormulaire(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        // the form is displayed
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

    // empty form display
    void doEffacer(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        // prepare the form template
        HttpSession session = request.getSession(true);        
        session.setAttribute("nom", "");
        session.setAttribute("age", "");
        // the form is displayed
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

    // form validation
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
        // we retrieve the button that caused the POST
        String bouton = request.getParameter("bouton").toLowerCase();
        // treatment according to the button that caused the POST
        if(bouton==null){
            doInit(request,response);
            return;
        }
        if("envoyer".equals(bouton)){
            doEnvoyer(request,response);
            return;
        }
        if("effacer".equals(bouton)){
            doEffacer(request,response);
            return;
        }
    }

    // form validation
    void doEnvoyer(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
        // parameters are retrieved
        String nom = request.getParameter("txtNom");
        String age = request.getParameter("txtAge");
        // stored in the session
        HttpSession session = request.getSession(true);        
        session.setAttribute("nom", nom);
        session.setAttribute("age", age);
        // the link back to the form is set in the view template [response, errors]
        request.setAttribute("lienRetourFormulaire", (String)params.get("lienRetourFormulaire"));    
        // parameter verification
        ArrayList<String> erreursAppel = new ArrayList<String>();
    ...
        // errors in the parameters?
        if (erreursAppel.size() != 0) {
            // send error page
            request.setAttribute("erreurs", erreursAppel);
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
            return;
        }
        // parameters are correct - send response page
        getServletContext().getRequestDispatcher((String)params.get("urlReponse")).forward(request,
                response);
        return;
    }

    // post
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
...
    }
}
  • السطر 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] باستخدام متصفح مع تعطيل ملفات تعريف الارتباط وحذف ملفات تعريف الارتباط الموجودة. يتم الحصول على الاستجابة التالية:

Image

فيما يلي شفرة المصدر التي يتلقاها المتصفح:

1
2
3
<form name="frmPersonne" action="validationFormulaire;jsessionid=9D4CC83FEFB51AE78B1FD71EC66F9EF3" method="post">
...
</form>

السطر 1: رمز الجلسة موجود في عنوان URL الهدف لـ POST.

دعونا نملأ النموذج ونرسله:

Image

فيما يلي شفرة المصدر التي يتلقاها المتصفح:

1
2
3
4
...
    <br>
    <a href="retourFormulaire;jsessionid=9D4CC83FEFB51AE78B1FD71EC66F9EF3">Retour au formulaire</a>
  </body>

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