10. برنامه وب MVC [personne] – نسخه ۵
10.1. Introduction
در این نسخه، دو تغییر ایجاد کردهایم:
اولین مورد مربوط به نحوه اطلاعرسانی کلاینت به سرور در مورد عملی است که میخواهد انجام دهد. تا کنون، این مورد با استفاده از پارامتری به نام [action] در درخواست GET یا POST کلاینت مشخص میشد. در اینجا، اقدام توسط آخرین عنصر URL درخواستشده توسط کلاینت مشخص خواهد شد، همانطور که در دنباله زیر نشان داده شده است:

در [1]، URLای که فرم به آن ارسال شده است [/personne5/do/validationFormulaire] است. این عنصر نهایی URL، یعنی [validationFormulaire]، به کنترلکننده امکان میدهد تا اقدام مورد نظر را تشخیص دهد. در [2]، POST که توسط لینک [Retour au formulaire] تحریک شده بود، در URL [/personne5/do/retourFormulaire] اجرا شد. در اینجا نیز، آخرین عنصر URL، [retourFormulaire]، به کنترلر میگوید که کدام عمل را انجام دهد.
ما این تغییر را معرفی میکنیم زیرا این روشی است که توسط محبوبترین فریمورکهای توسعه وب، مانند Struts یا Spring MVC استفاده میشود.
تمام آدرسهای URL در برنامه به شکل [/personne5/do/action] خواهند بود. فایل [web.xml] برای برنامه [/personne5] نشان میدهد که برنامه آدرسهای URL را به شکل [/do/*] میپذیرد:
<servlet-mapping>
<servlet-name>personne</servlet-name>
<url-pattern>/do/*</url-pattern>
</servlet-mapping>
کنترلکننده نام عملی را که باید انجام شود به شرح زیر بازیابی خواهد کرد:
متد [getPathInfo] از شیء [request] آخرین عنصر URL درخواست را برمیگرداند.
تغییر دوم مربوط به نحوه ذخیره ورودی کاربر بین چرخههای درخواست/پاسخ است. در حال حاضر، این اطلاعات در یک جلسه (session) ذخیره میشود. این رویکرد میتواند معایبی داشته باشد اگر کاربران زیادی وجود داشته باشند و حجم زیادی از دادهها برای هر یک از آنها برای ذخیره کردن باشد. در واقع، هر کاربر جلسه شخصی خود را دارد. علاوه بر این، یک جلسه پس از خروج کاربر برای مدتی فعال باقی میماند، مگر اینکه گزینهای برای خروج (log-out) در نظر گرفته شده باشد. بنابراین، ۱۰۰۰ جلسه ۱۰۰۰ بایتی، ۱ مگابایت حافظه را اشغال خواهند کرد. این همچنان یک نیاز متوسط است و برنامههای کمی به طور همزمان ۱۰۰۰ جلسه فعال دارند.
با این حال، جایگزینهایی برای جلسات وجود دارند که مصرف حافظه کمتری دارند و ارزش آشنایی با آنها را دارد. در اینجا، از روش کوکی استفاده خواهیم کرد. بیایید این را با یک مثال نشان دهیم.
مرحله ۱: کاربر یک فرم را ارسال میکند:
![]() |
این چرخه درخواست/پاسخ منجر به تبادلهای زیر، HTTP، بین کلاینت و سرور میشود:
[1] : [demande du client]
این یک POST استاندارد است. نکته خاصی برای اشاره در اینجا وجود ندارد، به جز اینکه با وجود اینکه ما قصد استفاده از یک جلسه (session) را نداریم، سرور وب به هر حال یکی ایجاد میکند. این موضوع از توکن جلسه (session token) که مرورگر در خط 11 به سرور بازمیفرستد و قبلاً از سرور دریافت کرده بود، قابل مشاهده است.
[2]: [réponse du serveur]
میتوانیم ببینیم که در خطوط ۳ و ۴، سربرگهای HTTP و [Set-Cookie] به مرورگر کلاینت ارسال شدهاند، یکی برای نام (خط ۳) و دیگری برای سن (خط ۴). مقادیر این کوکیها، مقادیری هستند که در خط 14 در سربرگهای POST و [1] بالا ارسال شدهاند.
مرحله ۲: بازگشت به فرم

این چرخه درخواست/پاسخ منجر به تبادلات زیر HTTP بین کلاینت و سرور میشود:
[1]: [demande du client]
در اینجا میبینیم که POST با کلیک بر روی لینک [Retour au formulaire] تحریک میشود. در خط ۱۱، میبینیم که مرورگر کوکیهایی را که دریافت کرده ([nom, age, JSESSIONID]) از طریق هدر HTTP ([Cookie]) به سرور بازمیفرستد. این نحوه عملکرد کوکیها است: کلاینت کوکیهایی را که سرور برایش ارسال کرده، به سرور بازمیفرستد. در این مثال، کنترلر مقادیر [pauline, 18] را دریافت میکند که باید آنها را در فیلدهای [txtNom, txtAge]ِ ویوی [formulaire] که در [2] نمایش داده شده، قرار دهد.
[2]: [réponse du serveur]
در اینجا نکته خاصی برای ذکر نیست، جز این واقعیت که در این پاسخ، سرور هیچ کوکیای ارسال نکرده است. این امر مانع از آن نمیشود که مرورگر در تبادل بعدی، تمام کوکیهایی را که از سرور دریافت کرده است، بازگرداند، حتی اگر این کار هیچ هدفی نداشته باشد. بنابراین، ما فشار بر حافظه در دسترس سرور را به قیمت افزایش جریان کاراکتر در تبادلات کلاینت/سرور کاهش میدهیم.
10.2. پروژه اکلیپس
برای ایجاد پروژه Eclipse [mvc-personne-05] برای برنامه وب [/personne5]، پروژه [mvc-personne-04] را با دنبال کردن رویهای که در بخش 6.2 توضیح داده شده است، کپی کنید.
![]() | ![]() |
10.3. پیکربندی برنامه وب [personne5]
فایل web.xml برای برنامه /personne5 به شرح زیر است:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>mvc-personne-05</display-name>
<!-- ServletPersonne -->
<servlet>
<servlet-name>personne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletPersonne
</servlet-class>
...
</servlet>
<!-- نگاشت ServletPersonne-->
<servlet-mapping>
<servlet-name>personne</servlet-name>
<url-pattern>/do/*</url-pattern>
</servlet-mapping>
<!-- فایلهای اصلی -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
این فایل به جز چند جزئیات با نسخه قبلی یکسان است:
- خط ۶: نام نمایشی برنامه وب به [mvc-personne-05] تغییر یافته است
- خط ۱۸: URLهایی که توسط برنامه پردازش میشوند به شکل [/do/*] هستند. قبلاً، فقط URL [/main] پردازش میشد. اکنون، به اندازه تعداد عملیاتهای قابل پردازش، 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="/do/formulaire"/>
- خط ۵: صفحه [index.jsp] کلاینت را به URL [/personne5/do/formulaire] هدایت میکند، که معادل دستور دادن به کنترلر برای اجرای اکشن [formulaire] است.
10.4. کد نما
ویوهای [formulaire, réponse, erreurs] تغییر بسیار کمی داشتهاند. تنها تغییر این است که اکشن قابل اجرا دیگر به همان شیوهای که قبلاً در یک فیلد مخفی به نام [action] در فرمهای ارسالشده تعریف میشد، مشخص نمیشود. اکنون این اقدام در URL مقصد فرمهای ارسالشده، c.a.d، در داخل ویژگی [action] تگ <form> تعریف میشود:
[formulaire.jsp]:
...
<html>
<head>
<title>Personne - formulaire</title>
<script language="javascript">
...
</script>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form name="frmPersonne" action="validationFormulaire" method="post">
...
</form>
</center>
</body>
</html>
- خط [13]: پارامتر فرم [action] پس از مدتی غیبت در نسخههای قبلی، دوباره ظاهر شده است. برای درک مقدار این ویژگی در اینجا، مهم است به یاد داشته باشید که تمام URLهایی که توسط برنامه پردازش میشوند، از شکل [/do/action] هستند. در خط [13]، مقدار ویژگی [action] یک URL نسبی (بدون شروع با /) است. بنابراین مرورگر، URL صفحهٔ در حال نمایش را به آن اضافه میکند و در نتیجه یک URL از شکل [/do/action] به دست میآید. عنصر آخر با URL نسبیِ ویژگی [action]ِ تگ <form> جایگزین میشود، که در نتیجه URL [/do/validationFormulaire] به عنوان هدفِ POST به دست میآید.
- میدان مخفی [action] ناپدید شده است
[réponse.jsp]:
...
<html>
...
<body>
...
<form name="frmPersonne" action="retourFormulaire" method="post">
</form>
<a href="javascript:document.frmPersonne.submit();">
${lienRetourFormulaire}
</a>
</body>
</html>
- ردیف [7]: هدف POST، [/do/retourFormulaire] خواهد بود
- میدان مخفی [action] در فرم در خطوط ۷–۸ ناپدید شده است.
[erreurs.jsp]:
...
<html>
...
<body>
...
<form name="frmPersonne" action="retourFormulaire" method="post">
</form>
<a href="javascript:document.frmPersonne.submit();">
${lienRetourFormulaire}
</a>
</body>
</html>
- ردیف [6]: هدف POST خواهد بود [/do/retourFormulaire]
- میدان مخفی [action] در فرم در خطوط 6–7 ناپدید شده است.
از خوانندگان دعوت میشود تا این نماهای جدید را با استفاده از رویکرد تشریحشده در نسخههای قبلی آزمایش کنند.
10.5. کنترلکننده [ServletPersonne]
کنترلکننده [ServletPersonne] برای برنامه وب [/personne5] اقدامات زیر را مدیریت خواهد کرد:
خیر. | درخواست | مبدأ | در حال پردازش |
۱ | [GET /personne5/do/formulaire] | URL وارد شده توسط کاربر | - ارسال نمای خالی [formulaire] |
۲ | [POST /person5/do/validationFormulaire] با پارامترهای [txtNom, txtAge] ارسال شد | با کلیک روی دکمه [Envoyer] در نما [formulaire] | - مقادیر پارامتر را بررسی کنید [txtNom, txtAge] - اگر نادرست باشند، نما [erreurs(erreurs)] را ارسال کنید - اگر صحیح باشند، نما [reponse(nom,age)] را ارسال کنید |
3 | [POST /person5/do/retourFormulaire] بدون هیچ پارامتری | روی لینک [بازگشت به کلیک کنید فرم] در نماها [réponse] و [erreurs]. | - ارسال نمای از پیش پرشده [formulaire] با آخرین مقادیر واردشده |
قالب کنترلر [ServletPersonne] با نسخه قبلی یکسان است. ما تغییرات اعمالشده در متدهای [doValidationFormulaire, doRetourFormulaire, doGet] را بررسی خواهیم کرد، زیرا متدهای [init, doInit, doPost] بدون تغییر باقی ماندهاند.
10.5.1. روش [doGet]
روش [doGet] اقدام قابل اجرا را به همان شیوهی نسخههای قبلی بازیابی نمیکند:
- خط ۱۲: اقدام قابل اجرا بازیابی میشود. این در قالب [/action] است.
- خطوط ۱۸–۲۲: پردازش اقدام [/formulaire] که توسط درخواست GET درخواست شده است
- خطوط ۲۳–۲۷: پردازش اقدام [/validationFormulaire] که توسط درخواست POST درخواست شده است
- خطوط ۲۸–۳۲: پردازش اقدام [/retourFormulaire] درخواستشده توسط درخواست POST
10.5.2. روش [doValidationFormulaire]
این متد درخواست شمارهٔ ۲، [POST /personne5/do/validationFormulaire]، را به همراه [txtNom, txtAge] در آیتمهای ارسالشده پردازش میکند. کد آن به شرح زیر است:
ویژگیهای جدید:
- متد [doValidationFormulaire] یکی از ویوها [réponse, erreurs] را برمیگرداند. صرفنظر از پاسخ، کنترلر دو کوکی را در آن تنظیم میکند (خطوط ۸–۹). یک کوکی با یک شیء [Cookie] نمایش داده میشود که سازند آن دو پارامتر را میپذیرد: کلید کوکی و مقدار مرتبط با آن.
- خط ۸: مقداری که برای نام وارد شده، در کوکی با کلید «name» قرار میگیرد.
- خط ۹: مقداری که برای 'age' وارد شده است در کوکی با کلید 'age' قرار میگیرد
- یک کوکی به پاسخ HTTP که با استفاده از متد [response.addCookie] به کلاینت ارسال میشود، اضافه میگردد. این پاسخ صرفاً در اینجا در حال آمادهسازی است. این پاسخ تنها زمانی واقعاً ارسال خواهد شد که صفحه JSP نمای ارسالشده به کلاینت اجرا شود.
10.5.3. روش [doRetourFormulaire]
این متد درخواست شماره 2، [POST /personne5/do/retourFormulaire]، را که حاوی هیچ دادهی ارسالشدهای نیست، پردازش میکند. کد آن به شرح زیر است:
ویژگیهای جدید:
روش [doRetourFormulaire] باید یک فرم از پیش پرشده با جدیدترین ورودیهای انجامشده را نمایش دهد. در نسخه قبلی، این موارد در جلسه (session) ذخیره میشدند. در این نسخه، دیگر از جلسه استفاده نمیشود؛ در عوض، از کوکیها برای ذخیره دادهها بین تبادلهای کلاینت-سرور استفاده میشود. زمانی که کلاینت اعتبارسنجی فرم را درخواست میکرد، در پاسخ، بسته به مورد، نمای [réponse] یا [erreurs] را دریافت میکرد که با دو کوکی با برچسبهای «name» و «age» همراه بود. هنگامی که کاربر روی لینک [Retour au formulaire] در هر یک از این دو نما کلیک میکند—که یک POST را در URL [/do/retourFormulaire] تحریک میکند—مرورگر دو کوکی را که دریافت کرده است به سمت سرور بازمیفرستد.
- خطوط ۴–۱۸: مقادیر کوکیهای دارای برچسب «name» و «age» بازیابی میشوند. به طرز عجیبی، هیچ روشی برای بهدستآوردن مقدار یک کوکی از روی کلید آن وجود ندارد. بنابراین مجبوریم روی هر یک از کوکیهای دریافتشده بهصورت حلقهای عبور کنیم.
- پس از انجام این کار، دو مقدار بهدستآمده در قالب نمای [formulaire] (خطوط ۲۰–۲۱) قرار میگیرند تا بتواند آنها را نمایش دهد.
10.6. Tests
پس از ادغام پروژه Eclipse با شناسه [personne-mvc-05]، Tomcat را راهاندازی یا مجدداً راهاندازی کنید، سپس URL با شناسه [http://localhost:8080/personne5] را درخواست کنید.


