Skip to content

12. برنامه وب MVC [personne] – نسخه ۷

12.1. Introduction

در این نسخه، فرض می‌کنیم که برخی از مرورگرهای کلاینت ممکن است غیرفعال کرده باشند:

  1. ارسال مجدد کوکی‌های ارسال‌شده توسط سرور
  2. اجرای کد جاوااسکریپت جاسازی‌شده در صفحات نمایش‌داده‌شده HTML

با این وجود، ما می‌خواهیم این نوع مرورگرها بتوانند از برنامه ما استفاده کنند. نکته ۲ ما را به نسخه ۲ برنامه ما بازمی‌گرداند، زیرا جاوااسکریپت از نسخه ۳ به بعد معرفی شد. نسخه ۲ برنامه را بدون جاوااسکریپت اجرا می‌کرد، بنابراین نکته ۲ حل شده است.

مدیریت نکته ۱ ممکن است دشوار باشد یا نباشد. نسخه ۶ برنامه ما بدون کوکی‌ها کار می‌کرد. با ادغام نسخه‌های ۲ و ۶، به نتیجه مورد نظر می‌رسیم. ما قصد داریم یک محدودیت اضافی اضافه کنیم: برنامه باید یک جلسه (session) را مدیریت کند. این یک محدودیت بی‌معنی نیست. در برنامه‌ای که کاربران باید احراز هویت شوند، سرور باید نام کاربری و رمز عبور کاربر را ذخیره کند تا مجبور نشود در هر صفحه‌ای که درخواست می‌کند، دوباره احراز هویت کند.

تا اینجا، ما از سه راه‌حل برای ذخیره‌سازی اطلاعات در طول مبادلات کلاینت–سرور استفاده کرده‌ایم:

  1. سشن
  2. کوکی‌ها
  3. میدان‌های مخفی.

راه حل ۲ را می‌توان کنار گذاشت، زیرا ممکن است مرورگر کلاینت استفاده از کوکی‌ها را غیرفعال کرده باشد.

راه حل سوم همان چیزی است که در نسخه ۶ استفاده می‌شود و قبلاً به آن پرداختیم. به دلایل امنیتی نمی‌توان از آن استفاده کرد. اگر جفت نام کاربری/رمز عبور در هر صفحه‌ای که به مرورگر ارسال می‌شود، تعبیه شود، این بدان معناست که این اطلاعات در هر تبادل کلاینت-سرور از طریق شبکه منتقل می‌شود. این امر برای امنیت برنامه مناسب نیست. بنابراین می‌توانیم استفاده از پروتکل HTTPS را که ارتباطات کلاینت و سرور را رمزگذاری می‌کند، در نظر بگیریم. با این حال، استفاده از آن برای هر صفحه در برنامه، بار کاری سرور را افزایش خواهد داد.

ممکن است بخواهید راه‌حل اول را به دلیل مبتنی بر کوکی بودن کنار بگذارید. در طول اولین تبادل بین کلاینت و سرور، سرور یک توکن جلسه (session token) را برای کلاینت ارسال می‌کند، که کلاینت سپس آن را با هر درخواست جدید برای سرور بازمی‌گرداند. به لطف این توکن، سرور می‌تواند کلاینت را تشخیص دهد و اطلاعاتی را که در طول یک تبادل قبلی ذخیره کرده بود، در اختیار آن قرار دهد. توکن جلسه توسط سرور در یک کوکی ارسال می‌شود. یک مرورگر که کوکی‌ها را غیرفعال نکرده باشد می‌تواند این کوکی را در درخواست‌های بعدی به سرور بازگرداند. اگر کوکی‌ها غیرفعال شده باشند، گزینه دیگری وجود دارد: مرورگر می‌تواند توکن جلسه را در URL درخواست بگنجاند. ما اکنون با بازگشت به تحلیل فایل [index.jsp] از نسخه ۴ می‌توانیم این را ببینیم:


<%@ 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"/>

توجه داشته باشید که خط ۵ بالا، کلاینت را به URL [/personne4/main?jsessionid=XX] هدایت می‌کند، که در آن XX توکن جلسه است، همانطور که در اسکرین‌شات زیر نشان داده شده است که پس از درخواست URL [http://localhost:8080/personne4] به دست آمده است:

Image

بیایید نگاهی دقیق‌تر بیندازیم که تگ <c:redirect> در رابطه با توکن جلسه چگونه کار می‌کند. بیایید یک مرورگر که کوکی‌ها را می‌پذیرد در نظر بگیریم. در زیر، مرورگر فایرفاکس را پیکربندی می‌کنیم:

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/person4/main;jsessionid=1ACA010A6BA28FB9E30A1D3184F574BC
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 0
Date: Tue, 23 May 2006 09:10:05 GMT
  • خط ۱: سرور به کلاینت دستور می‌دهد که هدایت (redirect) کند
  • خط ۳: سرور یک توکن جلسه مرتبط با ویژگی [JSESSIONID] را ارسال می‌کند
  • خط ۴: 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
  • خط ۱۰: مرورگر URL هدایت (redirect) را همراه با توکن جلسه درخواست می‌کند. به همین دلیل مرورگر این URL را در اسکرین‌شات نمایش می‌دهد.
  • خط ۱۰: مرورگر توکن جلسه را که سرور در تبادل قبلی برای آن ارسال کرده بود، بازمی‌فرستد. این همان روشی است که کوکی‌ها معمولاً وقتی در مرورگر کلاینت فعال هستند، کار می‌کنند. اگر اینطور نباشد، کوکی‌های دریافت‌شده بازنمی‌گردند.

سرور به این درخواست دوم با موارد زیر پاسخ داد:

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

این دقیقاً همان درخواست قبلی است، با یک تفاوت: در خط ۱۰، مرورگر توکن جلسه را که در اولین تبادل دریافت کرده بود، بازمی‌فرستد. بار دیگر، این رفتار در صورتی که کوکی‌های مرورگر فعال باشند، طبیعی است.

سرور پاسخ زیر را ارسال کرد:

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

این به کلاینت دستور می‌دهد که هدایت (redirect) کند. از آنجایی که یک توکن جلسه (session token) از کلاینت دریافت کرده است، جلسه را ادامه می‌دهد و توکن جلسه جدیدی ارسال نمی‌کند. به همین دلیل، تگ <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/person4/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
  • خطوط ۱–۹: اولین درخواست مرورگر. این درخواست کوکی جلسه (session cookie) ارسال نمی‌کند.
  • خطوط ۱۱–۱۷: پاسخ سرور، دستور می‌دهد مرورگر به یک URL دیگر هدایت شود. در خط ۱۳ یک کوکی جلسه ارسال می‌کند: تگ <c:redirect> توکن را در URL هدایت در خط ۱۴ گنجانده است.
  • خطوط ۱۹–۲۷: درخواست دوم مرورگر. این خط، کوکی جلسه را که به تازگی توسط سرور ارسال شده است بازنمی‌گرداند زیرا کوکی‌ها غیرفعال هستند.
  • خطوط ۲۹–۳۳: پاسخ سرور. می‌بینیم که اگرچه مرورگر کوکی جلسه را ارسال نکرده است، اما سرور برخلاف انتظار، جلسه جدیدی را آغاز نمی‌کند. این موضوع از این واقعیت مشهود است که سربرگ HTTP [Set-Cookie] را که در خط ۱۳ ارسال کرده بود، ارسال نمی‌کند. این بدان معناست که جلسه قبلی را ادامه می‌دهد. این سرور به لطف توکن جلسه‌ای که در URL درخواست‌شده توسط مرورگر در خط ۱۹ موجود بود، توانست این جلسه را بازیابی کند.

شایان ذکر است که سرور یک جلسه را با بازیابی توکن جلسه‌ای که توسط کلاینت ارسال شده است، به دو روش ممکن پیگیری می‌کند:

  • در هدر HTTP [Set-Cookie] ارسال‌شده توسط کلاینت
  • در URL درخواست‌شده توسط کلاینت

اکنون، با استفاده از همان مرورگر، بیایید URL [http://localhost:8080/personne4] را دوباره با تایپ دستی آن درخواست کنیم، همانطور که هنگام فعال بودن کوکی‌ها انجام شد. سپس صفحه زیر را دریافت می‌کنیم:

Image

این نتیجه با نتیجه‌ای که هنگام فعال بودن کوکی‌ها به دست آمد متفاوت است: توکن جلسه در URL نمایش‌داده‌شده توسط مرورگر گنجانده شده است. بیایید این نتیجه را بدون بررسی مبادلات HTTP که رخ داده است، توضیح دهیم:

[cookies autorisés]

  • در طول درخواست دوم برای URL [http://localhost:8080/personne4]، مرورگر کلاینت کوکی سشن را که در طول درخواست اول برای همان URL از سرور دریافت کرده بود، بازگردانده بود. بنابراین تگ <c:redirect> توکن سشن را در آدرس هدایت (redirect) لحاظ نکرده بود.

[cookies inhibés]

  • در طول درخواست دوم برای URL [http://localhost:8080/personne4]، مرورگر کلاینت کوکی جلسه را که در طول درخواست اول برای همان URL از سرور دریافت کرده بود، ارسال نمی‌کند، زیرا کوکی‌های آن غیرفعال هستند. بنابراین تگ <c:redirect> توکن جلسه را در URL هدایت شده قرار می‌دهد. به همین دلیل است که در اسکرین‌شات بالا مشاهده می‌شود.

تگ‌های <c:redirect> و <c:url> امکان درج توکن جلسه در آدرس‌های URL را فراهم می‌کنند. این راه‌حل پیشنهادی در اینجا است.

12.2. پروژه اکلیپس

برای ایجاد پروژه Eclipse با نام [mvc-personne-07] برای برنامه وب [/personne7]، با دنبال کردن رویه‌ای که در بخش 6.2 توضیح داده شده است، پروژه [mvc-personne-06] را کپی کنید.

12.3. پیکربندی برنامه وب [personne7]

فایل web.xml برای برنامه /personne7 به شرح زیر است:


<?xml version="1.0" encoding="UTF-8"?>
...
    <display-name>mvc-personne-07</display-name>
...

این فایل به جز خط ۳ که در آن نام نمایشی وب‌اپلیکیشن به [mvc-personne-07] تغییر یافته، با نسخه قبلی یکسان است. صفحه اصلی [index.jsp] بدون تغییر باقی می‌ماند.


...
<c:redirect url="/do/formulaire"/>

12.4. کد نما

ویوهای [formulaire, réponse, erreurs] به حالت قبلی خود در نسخهٔ 2، یعنی c.a.d، بدون جاوااسکریپت بازمی‌گردند. با این حال، آن‌ها برچسب‌های JSTL را از نسخه‌های اخیر حفظ می‌کنند.

12.4.1. نما [formulaire]

Image

دکمه‌های مرتبط با کد جاوااسکریپت حذف شده‌اند.

[formulaire.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>
  • خط ۱۴: URL مقصد برای POST با استفاده از تگ <c:url> نوشته شده است تا توکن جلسه در صورتی که کلاینت مرورگری باشد که هدر HTTP و [Cookie] را ارسال نمی‌کند، گنجانده شود.
  • این فرم دارای دو دکمه از نوع [submit] است: [Envoyer] (خط ۲۸) و [Effacer] (خط ۳۰). هر دو دکمه نام یکسانی دارند: bouton. وقتی دکمه POST کلیک می‌شود، مرورگر پارامتر را ارسال خواهد کرد:
  • button=Submit اگر POST توسط دکمه [Submit] فعال شده باشد
  • button=Delete اگر POST توسط دکمه [حذف] تحریک شده باشد

این پارامتر به ما کمک می‌کند تا اقدام دقیق مورد نظر را مشخص کنیم، زیرا URL [/do/validationFormulaire] اکنون با دو اقدام متمایز مطابقت دارد.

12.4.2. نما [réponse]

Image

[réponse.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>

  • خط ۲۴: URL مقصد برای HREF با استفاده از تگ <c:url> نوشته شده است تا توکن جلسه در صورتی که کلاینت یک مرورگر باشد که هدر HTTP [Cookie] را ارسال نمی‌کند، گنجانده شود.

12.4.3. نما [erreurs]

Image

[erreurs.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>

  • خط ۱۸: URL مقصد برای HREF با استفاده از تگ <c:url> نوشته شده است تا توکن جلسه در صورتی که کلاینت یک مرورگر باشد که هدر HTTP [Cookie] را ارسال نمی‌کند، گنجانده شود.

از خوانندگان دعوت می‌شود تا این نماهای جدید را با استفاده از رویکرد تشریح‌شده در نسخه‌های قبلی آزمایش کنند.

12.5. کنترل‌کننده [ServletPersonne]

کنترلر [ServletPersonne] برای برنامه وب [/personne7] به شرح زیر است:

package istia.st.servlets.personne;

...

@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     //پارامترهای نمونه
    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 {

...
         // بازیابی روش ارسال درخواست
        String méthode=request.getMethod().toLowerCase();
         // عملکردی را که باید اجرا شود بازیابی می‌کنیم
        String action=request.getPathInfo();
...
        if(méthode.equals("post") && action.equals("/validationFormulaire")){
             //اعتبارسنجی فرم ورودی
            doValidationFormulaire(request,response);
            return;
        }
        if(méthode.equals("get") && action.equals("/retourFormulaire")){
             //بازگشت به فرم ورودی
            doRetourFormulaire(request,response);
            return;
        }
         // سایر موارد
        doInit(request,response);
    }

     //نمایش فرم خالی
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
...
    }

     //نمایش فرم از پیش پرشده
    void doRetourFormulaire(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // فرم نمایش داده می‌شود
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

     //نمایش فرم خالی
    void doEffacer(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // آماده‌سازی قالب فرم
        HttpSession session = request.getSession(true);        
        session.setAttribute("nom", "");
        session.setAttribute("age", "");
         //فرم نمایش داده می‌شود
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

     //اعتبارسنجی فرم
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
         // بازیابی دکمه‌ای که POST را فعال کرد
        String bouton = request.getParameter("bouton").toLowerCase();
         //پردازش بر اساس دکمه‌ای که POST را فعال کرده است
        if(bouton==null){
            doInit(request,response);
            return;
        }
        if("envoyer".equals(bouton)){
            doEnvoyer(request,response);
            return;
        }
        if("effacer".equals(bouton)){
            doEffacer(request,response);
            return;
        }
    }

     //اعتبارسنجی فرم
    void doEnvoyer(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
         // بازیابی پارامترها
        String nom = request.getParameter("txtNom");
        String age = request.getParameter("txtAge");
         // که در جلسه ذخیره می‌شوند
        HttpSession session = request.getSession(true);        
        session.setAttribute("nom", nom);
        session.setAttribute("age", age);
         //لینک بازگشت به فرم در قالب نما قرار داده می‌شود [réponse, erreurs]
        request.setAttribute("lienRetourFormulaire", (String)params.get("lienRetourFormulaire"));    
         // پارامترها را بررسی کنید
        ArrayList<String> erreursAppel = new ArrayList<String>();
    ...
         //آیا در پارامترها خطایی وجود دارد؟
        if (erreursAppel.size() != 0) {
             // صفحه خطا ارسال می‌شود
            request.setAttribute("erreurs", erreursAppel);
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
            return;
        }
         //پارامترها صحیح هستند – ارسال صفحه پاسخ
        getServletContext().getRequestDispatcher((String)params.get("urlReponse")).forward(request,
                response);
        return;
    }

     //ارسال
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
...
    }
}
  • خط ۳۵: اکشن [/retourFormulaire] توسط یک GET انجام می‌شود و دیگر مانند نسخه قبلی توسط یک POST انجام نمی‌شود.
  • سطور ۷۰–۸۷: اقدام [/validationFormulaire] توسط POST فراخوانی می‌شود که به نوبه خود با کلیک روییکی از دکمه‌های [Envoyer] یا [Effacer] در نمای [formulaire]. متد [doValidationFormulaire] این دو حالت را با دو روش متفاوت مدیریت می‌کند.
  • خطوط ۹۰–۱۰۳: متد [doEnvoyer] معادل متد [doValidationFormulaire] در نسخه قبلی است. داده‌های وارد شده در جلسه (session) قرار داده می‌شوند (خطوط ۹۶–۹۸)، در حالی که در نسخه قبلی در پرس‌وجو (query) قرار می‌گرفتند.
  • خطوط ۵۸–۶۷: روش جدید [doEffacer] باید یک فرم خالی نمایش دهد. می‌توانستیم روش [doInit] را فراخوانی کنیم که قبلاً این کار را انجام می‌دهد. در اینجا، همچنین از این فرصت استفاده می‌کنیم تا عناصر [nom, age] را از جلسه پاک کنیم تا همچنان آخرین وضعیت فرم را منعکس کند.
  • خطوط ۵۰–۵۵: سیستم را دستور می‌دهیم تا نمای [formulaire] را بدون هیچ‌گونه inicialization ظاهری برای قالب نما نمایش دهد. این قالب در واقع از عناصر [nom, age] تشکیل شده است که از قبل در جلسه موجود هستند. هیچ اقدام بیشتری لازم نیست.

12.6. Tests

پس از ادغام پروژه Eclipse با شناسه [personne-mvc-07Tomcat را راه‌اندازی یا مجدداً راه‌اندازی کنید، سپس با استفاده از مرورگری که کوکی‌ها در آن غیرفعال شده و هرگونه کوکی موجود حذف شده است، URL با شناسه [http://localhost:8080/personne7] را درخواست کنید. پاسخ زیر دریافت می‌شود:

Image

کد منبع دریافتی توسط مرورگر به شرح زیر است:

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

خط ۱: توکن جلسه در URL مقصد POST قرار دارد.

بیایید فرم را پر کرده و آن را ارسال کنیم:

Image

کد منبع دریافت‌شده توسط مرورگر به شرح زیر است:

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

خط ۳: توکن جلسه در URL مقصد لینک قرار دارد.