Skip to content

6. برنامه وب MVC [personne] – نسخه ۲

اکنون ما گونه‌های متفاوتی از برنامه قبلی [/personne1] را پیشنهاد می‌کنیم که آن را [/personne2, /personne3, ...] می‌نامیم. این گونه‌ها معماری اصلی برنامه را تغییر نمی‌دهند که به شرح زیر باقی می‌ماند:

Image

برای این گونه‌ها، توضیحات خود را مختصر نگه می‌داریم. ما فقط تغییرات ایجاد شده را در مقایسه با نسخه قبلی تشریح خواهیم کرد.

6.1. Introduction

اکنون پیشنهاد می‌کنیم مدیریت جلسه را به برنامه خود اضافه کنیم. بیایید نکات زیر را به یاد بیاوریم:

  • گفتگوی کلاینت-سرور HTTP از مجموعه‌ای از توالی‌های درخواست-پاسخ تشکیل شده است که از یکدیگر مستقل هستند
  • جلسه به‌عنوان حافظه‌ای بین توالی‌های مختلف درخواست-پاسخ از یک کاربر واحد عمل می‌کند. اگر N کاربر وجود داشته باشد، N جلسه وجود خواهد داشت.

سلسله صفحه‌های نمایش زیر نشان می‌دهد که برای عملکرد برنامه در حال حاضر چه چیزی لازم است:


تبادل شماره ۱


demande
réponse

ویژگی جدید، لینک بازگشت به فرم است که برای مشاهده [erreurs] اضافه شده است.


تبادل شماره ۲


demande
réponse

در تبادل شمارهٔ ۱، کاربر مقادیر (xx، yy) را برای جفت (نام، سن) ارائه داد. اگر در طول تبادل، سرور از این مقادیر مطلع شود، در پایان تبادل آن‌ها را «فراموش» می‌کند. با این حال، مشاهده می‌شود که در طول تبادل شماره ۲، سرور قادر است این مقادیر را دوباره در پاسخ خود نمایش دهد. این مفهوم «سشن» است که در این مورد به سرور وب اجازه می‌دهد داده‌ها را در طول تبادلات متوالی کلاینت-سرور ذخیره کند. راه‌حل‌های ممکن دیگری نیز برای این مشکل وجود دارد.

در طول تبادل شماره ۱، سرور جفت (نام، سن) را که کلاینت برایش ارسال کرده است، در جلسه ذخیره می‌کند تا بتواند آن را در طول تبادل شماره ۲ نمایش دهد.

در اینجا یک مثال دیگر از نحوه پیاده‌سازی یک جلسه بین دو تبادل آورده شده است:


تبادل شماره ۱


demande
réponse

ویژگی جدید، لینک بازگشت به فرم است که به صفحه پاسخ اضافه شده است.


تبادل شماره ۲


demande
réponse

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

برای ایجاد پروژه Eclipse با شناسه [mvc-personne-02] برای برنامه وب [/personne2]، پروژه Eclipse با شناسه [mvc-personne-01] را به‌منظور حفظ پیکربندی موجود کپی می‌کنیم. برای انجام این کار، مراحل زیر را دنبال کنید:

[clic droit sur projet mvc-personne-01 -> Copy]:

Image

سپس [clic droit dans Package Explorer -> Paste]:

- بیایید نام پروژه جدید را [1] و نام یک پوشه موجود اما خالی را [2] مشخص کنیم

سپس پروژه [mvc-personne-02] ایجاد می‌شود:

Image

فعلاً، این پروژه با پروژه [mvc-personne-01] یکسان است. قبل از اینکه بتوانیم از آن استفاده کنیم، باید چند تغییر دستی در آن ایجاد کنیم. بیایید به نمای [Servers] برویم و سعی کنیم این برنامه جدید را به برنامه‌های تحت مدیریت Tomcat اضافه کنیم:

می‌توانیم ببینیم که در [1]، پروژه جدید [mvc-personne-02] توسط Tomcat شناسایی نمی‌شود. برای اینکه Tomcat آن را شناسایی کند، باید یک فایل پیکربندی برای پروژه [mvc-personne-02] اصلاح شود. بیایید از گزینه [File / Open File] برای باز کردن فایل [<mvc-personne-02>/.settings/.component] استفاده کنیم:


<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId">
<wb-module deploy-name="mvc-personne-01">
<wb-resource deploy-path="/" source-path="/WebContent"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src"/>
<property name="java-output-path" value="/build/classes/"/>
<property name="context-root" value="personne1"/>
</wb-module>
</project-modules>

خط ۳ نام ماژول وبی را که باید در Tomcat مستقر شود مشخص می‌کند. در اینجا این نام با نام پروژه [mvc-personne-01] یکسان است. ما آن را به [mvc-personne-02] تغییر می‌دهیم:


<wb-module deploy-name="mvc-personne-02">

علاوه بر این، می‌توانیم از این فرصت استفاده کرده و در خط ۷، نام زمینهٔ برنامه [mvc-personne-02] را که با نام پروژه [mvc-personne-01] تداخل دارد، اصلاح کنیم:


<property name="context-root" value="personne2"/>

این تغییر دوم را می‌توان مستقیماً در خود Eclipse انجام داد. با این حال، من نتوانستم راهی برای انجام تغییر اول بدون مراجعه به فایل پیکربندی پیدا کنم.

پس از انجام این کار، فایل جدید [.content] را ذخیره می‌کنیم، سپس از اکلیپس خارج شده و آن را مجدداً راه‌اندازی می‌کنیم تا تغییرات اعمال شوند.

پس از راه‌اندازی مجدد اکلیپس، بیایید عملی را که قبلاً با خطا مواجه شده بود، امتحان کنیم:

این بار، پروژه [mvc-personne-02] به درستی شناسایی می‌شود. آن را به پروژه‌هایی که برای اجرا روی Tomcat پیکربندی شده‌اند اضافه می‌کنیم:

Image

6.3. پیکربندی برنامه وب [personne2]

فایل web.xml برای اپلیکیشن /personne2 به شرح زیر است:


<?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-02</display-name>
    <!--  ServletPersonne -->
    <servlet>
        <servlet-name>personne</servlet-name>
        <servlet-class>
            istia.st.servlets.personne.ServletPersonne
        </servlet-class>
        <init-param>
            <param-name>urlReponse</param-name>
            <param-value>
                /WEB-INF/vues/reponse.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlErreurs</param-name>
            <param-value>
                /WEB-INF/vues/erreurs.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlFormulaire</param-name>
            <param-value>
                /WEB-INF/vues/formulaire.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlControleur</param-name>
            <param-value>
                main
            </param-value>
        </init-param>
        <init-param>
            <param-name>lienRetourFormulaire</param-name>
            <param-value>
                Retour au formulaire
            </param-value>
        </init-param>
    </servlet>
    <!--  نگاشت ServletPersonne-->
    <servlet-mapping>
        <servlet-name>personne</servlet-name>
        <url-pattern>/main</url-pattern>
    </servlet-mapping>
    <!--  فایل‌های میزبان -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

این فایل با نسخه قبلی یکسان است، با این تفاوت که دو پارامتر راه‌اندازی جدید را اعلام می‌کند:

  • خط ۶: نام نمایشی برنامه وب به [mvc-personne-02] تغییر یافته است
  • خطوط ۳۱–۳۶: پارامتر پیکربندی به نام [urlControleur] را تعریف می‌کند که URL [main] است که به servlet [ServletPersonne] منتهی می‌شود
  • خطوط ۳۷–۴۲: پارامتر پیکربندی‌ای به نام [lienRetourFormulaire] تعریف می‌شود که متن لینک بازگشت به فرم در صفحات JSP، [erreurs.jsp] و [reponse.jsp] است.

صفحهٔ اصلی [index.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">
<%
  response.sendRedirect("/personne2/main");
%>
  • خط ۵: صفحه [index.jsp] کلاینت را به URL کنترل‌کننده [ServletPersonne] برای برنامه [/personne2] هدایت می‌کند.

6.4. کد نما

6.4.1. نما [formulaire]

این نما با نسخه قبلی یکسان است:

Image

این صفحه توسط صفحات زیر تولید می‌شود: JSP و [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">
<%
    // داده‌ها از قالب بازیابی می‌شوند
  String nom=(String)session.getAttribute("nom");
  String age=(String)session.getAttribute("age");
  String urlAction=(String)request.getAttribute("urlAction");
%>
    
<html>
    <head>
      <title>Personne - formulaire</title>
  </head>
  <body>
      <center>
        <h2>Personne - formulaire</h2>
      <hr>
      <form action="<%=urlAction%>" 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" value="Envoyer"></td>
            <td><input type="reset" value="Rétablir"></td>
            <td><input type="button" value="Effacer"></td>
          </tr>
        </table>
        <input type="hidden" name="action" value="validationFormulaire"> 
      </form>
    </center>
  </body>
</html>

ویژگی‌های جدید:

  • خط ۱۹: فرم اکنون دارای یک ویژگی [action] است که مقدار آن URL‌ای است که مرورگر باید هنگام کلیک کاربر روی دکمه [Envoyer] از نوع submit، مقادیر فرم را به آن ارسال کند. متغیر [urlAction] مقدار action="main" را خواهد داشت. نما [formulaire] پس از انجام این اقدامات کاربر نمایش داده می‌شود:
  • درخواست اولیه: GET /person2/main
  • کلیک بر روی لینک [Retour au formulaire]: GET /person2/main?action=retourFormulaire

از آنجایی که ویژگی [action] یک URL مطلق (شروع‌شونده با /) را مشخص نمی‌کند، بلکه یک URL نسبی (شروع‌نشده با /) است، مرورگر از بخش اول URL صفحه فعلی نمایش داده شده، یعنی [/personne2]، استفاده کرده و URL نسبی را به آن اضافه می‌کند. بنابراین، URL برای POST، همان [/personne2/main]، یعنی URL کنترل‌کننده، خواهد بود. این درخواست، POST، با پارامترهای [txtNom, txtAge, action] از خطوط 23، 27 و 38 همراه خواهد بود.

  • خط ۸: مقدار عنصر [urlAction] در مدل بازیابی می‌شود. این مقدار در ویژگی‌های درخواست جاری جستجو می‌شود. از آن در خط ۱۹ استفاده خواهد شد.
  • خطوط ۶–۷: مقادیر عناصر [nom, age] در مدل بازیابی می‌شوند. این مقادیر در ویژگی‌های جلسه جستجو می‌شوند و مانند نسخه قبلی دیگر در ویژگی‌های پرس‌وجو نیستند. این کار برای برآورده کردن الزامات پرس‌وجوی [GET /personne2/main?action=retourFormulaire] برای پیوند بین نماهای [réponse] و [erreurs] انجام می‌شود. پیش از نمایش این دو نما، کنترل‌کننده داده‌های وارد شده در فرم را در جلسه (session) قرار می‌دهد، که این امکان را فراهم می‌کند تا هنگام استفاده کاربر از لینک [Retour au formulaire] از نماهای [réponse] و [erreurs]، این داده‌ها بازیابی شوند.

6.4.2. نما [reponse]

این نما، مقادیر وارد شده در فرم را در صورتی که معتبر باشند، نمایش می‌دهد:

در مقایسه با نسخه قبلی، ویژگی جدید لینک [Retour au formulaire] است. نما توسط صفحه زیر تولید می‌شود: JSP [reponse.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">


<%
    //  بازیابی داده‌ها از مدل
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Personne - réponse</h2>
    <hr>
    <table>
        <tr>
          <td>Nom</td>
        <td><%= nom %>
      </tr>
        <tr>
          <td>Age</td>
        <td><%= age %>
      </tr>
    </table>      
    <br>
    <a href="?action=retourFormulaire"><%= lienRetourFormulaire %></a>
  </body>
</html>
  • خط ۳۱: لینک بازگشت به فرم. این لینک دو مؤلفه دارد:
    • هدف [href="?action=retourFormulaire"]. نما [réponse] پس از POST از فرم [formulaire.jsp] در URL [/personne2/main] نمایش داده می‌شود. بنابراین این URL دوم است که هنگام نمایش نما [réponse] در مرورگر نمایش داده می‌شود. کلیک بر روی لینک [Retour au formulaire] سپس یک درخواست GET را از مرورگر به URL مشخص‌شده توسط ویژگی [href] لینک، که در این مورد «?action=retourFormulaire» است، ارسال می‌کند. اگر هیچ URL در [href] وجود نداشته باشد، مرورگر از URL نمای در حال نمایش، c.a.d. [/personne2/main]. در نهایت، کلیک بر روی لینک [Retour au formulaire] یک درخواست GET را از مرورگر به URL [/personne2/main?action=retourFormulaire] ارسال می‌کند، c.a.d – URL کنترل‌کنندهٔ برنامه – به همراه پارامتر [action] تا به آن بگوید چه کاری انجام دهد.
    • متن لینک. این بخشی از قالب ارسال‌شده توسط کنترلر به صفحه را تشکیل می‌دهد و در خط ۱۰ بازیابی می‌شود.

6.4.3. ویوی [erreurs]

این نما خطاهای ورودی را به صورت زیر گزارش می‌کند:

در مقایسه با نسخه قبلی، ویژگی جدید لینک [Retour au formulaire] است. این نما توسط صفحه زیر تولید می‌شود: JSP [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">
<%@ page import="java.util.ArrayList" %>

<%
//بازیابی داده‌ها از مدل
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs"); 
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>
    <ul>
        <%
          for(int i=0;i<erreurs.size();i++){
            out.println("<li>" + (String) erreurs.get(i) + "</li>\n");
        }//برای
      %>
    </ul>
    <br>
    <a href="?action=retourFormulaire"><%= lienRetourFormulaire %></a>
  </body>
</html>

  • خط ۲۶: لینک بازگشت به فرم. این لینک با لینکی که در نمای [réponse] وجود دارد یکسان است. از خوانندگان دعوت می‌شود در صورت لزوم به توضیحات ارائه‌شده برای آن نما مراجعه کنند.

6.5. آزمایش نماها

برای آزمایش نماهای قبلی، صفحات آن‌ها JSP را در پوشه /WebContent/JSP پروژه Eclipse کپی می‌کنیم:

Image

سپس، در پوشه JSP، صفحات به شرح زیر اصلاح می‌شوند:

[formulaire.jsp]:


...
<%
  //-- تست: ایجاد قالب صفحه
  session.setAttribute("nom","tintin");
  session.setAttribute("age","30");
  request.setAttribute("urlAction","main");
%>

<%
    //داده‌ها را از قالب بازیابی می‌کند
  String nom=(String)session.getAttribute("nom");
  String age=(String)session.getAttribute("age");
  String urlAction=(String)request.getAttribute("urlAction");
%>

خطوط ۴–۵ برای ایجاد قالب مورد نیاز صفحه در خطوط ۱۱–۱۳ اضافه شده‌اند.

[reponse.jsp]:



<%
  //-- تست: ایجاد قالب صفحه
  request.setAttribute("nom","milou");
  request.setAttribute("age","10");
  request.setAttribute("lienRetourFormulaire","Retour au formulaire");
%>

<%
    //داده‌ها را از قالب بازیابی می‌کند
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>


خطوط ۴–۶ اضافه شده‌اند تا قالب مورد نیاز صفحه در خطوط ۱۱–۱۳ ایجاد شود.

[erreurs.jsp]:



<%
  //-- تست: ایجاد قالب صفحه
  ArrayList<String> erreurs1=new ArrayList<String>();
  erreurs1.add("erreur1");
  erreurs1.add("erreur2");
  request.setAttribute("erreurs",erreurs1);
  request.setAttribute("lienRetourFormulaire","Retour au formulaire");
%>

<%
//داده‌ها را از قالب بازیابی می‌کند
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs"); 
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>


خطوط ۴–۸ برای ایجاد قالب مورد نیاز صفحه در خطوط ۱۳–۱۴ اضافه شده‌اند.

بیایید اگر تا کنون انجام نشده است، Tomcat را راه‌اندازی کنیم، سپس آدرس‌های URL زیر را درخواست کنیم:

 

ما در واقع نماهای مورد انتظار را دریافت می‌کنیم.

6.6. کنترلر [ServletPersonne]

کنترل‌کننده [ServletPersonne] برای برنامه وب [/personne2] اقدامات زیر را مدیریت خواهد کرد:

خیر.
درخواست
مبدأ
در حال پردازش
۱
[GET /personne2/main]
URL وارد شده توسط کاربر
- ارسال نمای خالی [formulaire]
2
[POST /personne2/main]
با پارامترها [txtNom,
txtAge, action] ارسال شد
روی دکمه کلیک کنید
[Envoyer] در نما
[formulaire]
- مقادیر پارامترها را بررسی کنید [txtNom, txtAge]
- اگر نادرست باشند، نما را ارسال کنید [erreurs(erreurs)]
- اگر صحیح هستند، نما [reponse(nom,age)] را ارسال کنید
3
[GET /person2/main?
action=returnToForm]
روی [بازگشت به کلیک کنید
فرم] در
response] و [erreurs].
- ارسال نمای [formulaire]، با مقادیر واردشدهٔ اخیر از پیش پرشده

بنابراین ما یک اقدام جدید برای رسیدگی داریم: [GET /personne2/main?action=retourFormulaire].

6.6.1. اسکلت کنترل‌کننده

اسکلت کنترلر برای [ServletPersonne] تقریباً با نسخه قبلی یکسان است:

package istia.st.servlets.personne;

...
import javax.servlet.http.HttpSession;

@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
    ...

     // ابتدا
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
        ...
    }

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

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

     //نمایش فرم از پیش پرشده
    void doRetourFormulaire(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        ...
    }

     //اعتبارسنجی فرم
    void doValidationFormulaire(HttpServletRequest request,
    ...
    }

     //ارسال
    public void doPost(HttpServletRequest request, HttpServletResponse response)
    ...
    }
}

ویژگی‌های جدید:

  • خط ۴: استفاده از یک جلسه نیازمند وارد کردن بسته [HttpSession] است
  • سطور ۲۸–۳۰: متد جدید [doRetourFormulaire] اقدام جدید [GET /personne2/main?action=retourFormulaire] را مدیریت می‌کند.

6.6.2. ابتدایی‌سازی کنترل‌کننده [init]

متد [init] با نسخه قبلی یکسان است. این متد بررسی می‌کند که عناصری که در آرایه [paramètres] اعلام شده‌اند در فایل [web.xml] موجود باشند:

1
2
3
4
5
6
public class ServletPersonne extends HttpServlet {
     // پارامترهای نمونه
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse","urlControleur","lienRetourFormulaire"};
  private Map params=new HashMap<String,String>();
  • خط ۵: پارامترهای [urlControleur] (URL کنترل‌کننده) و [lienRetourFormulaire] (متن پیوند برای نماهای [réponse] و [erreurs]) اضافه شده‌اند.

6.6.3. متد [doGet]

متد [doGet] باید اقدام [GET /personne2/main?action=retourFormulaire] را که قبلاً وجود نداشت، مدیریت کند:

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

         //بررسی نحوهٔ راه‌اندازی سرولت
        if (erreursInitialisation.size() != 0) {
             // ارسال مجدد به صفحهٔ خطا
            request.setAttribute("erreurs", erreursInitialisation);
            request.setAttribute("lienRetourFormulaire", "");
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
             //پایان
            return;
        }
         // متد مورد استفاده برای ارسال درخواست را بازیابی می‌کند
        String méthode=request.getMethod().toLowerCase();
         // اکشن قابل اجرا را بازیابی می‌کنیم
        String action=request.getParameter("action");
         // عمل؟
        if(action==null){
            action="init";
        }
         // اجرای اقدام
        if(méthode.equals("get") && action.equals("init")){
             // راه‌اندازی برنامه
            doInit(request,response);
            return;
        }
        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);
    }
  • خطوط ۶–۱۴: سیستم بررسی می‌کند که آیا فهرست خطاهای инициализация خالی است یا خیر. اگر این‌طور نباشد، نمای [erreurs(erreursInitialisation)] را نمایش می‌دهد که خطا(ها) را گزارش خواهد کرد.

برای درک این کد، باید قالب نما [erreurs] را به یاد بیاورید:


<%
//بازیابی داده‌ها از قالب
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs"); 
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>

ویوی [erreurs] منتظر یک عنصر کلیدی به نام «errors» در درخواست است. کنترلر این عنصر را در خط ۸ ایجاد می‌کند. همچنین منتظر یک عنصر کلیدی به نام «lienRetourFormulaire» است. کنترلر این عنصر را در خط ۹ ایجاد می‌کند. در اینجا، متن لینک خالی خواهد بود. بنابراین هیچ لینکی در نمای [erreurs] که ارسال می‌شود، وجود نخواهد داشت. دلیل این امر آن است که اگر در حین راه‌اندازی برنامه خطاهایی رخ داده باشد، باید دوباره پیکربندی شود. نیازی نیست که به کاربر گزینه ادامه استفاده از برنامه از طریق یک لینک ارائه شود.

  • خطوط ۳۴–۳۷: پردازش اقدام جدید [GET /personne2/main?action=retourFormulaire]

6.6.4. متد [doInit]

این متد درخواست شماره ۱، [GET /personne2/main] را پردازش می‌کند. برای این درخواست، باید نمای خالی [formulaire(nom,age)] را بازگرداند. کد آن به شرح زیر است:

     //نمایش فرم خالی
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         //بازیابی جلسه کاربر
        HttpSession session = request.getSession(true);        
         //ارسال فرم خالی
        session.setAttribute("nom", "");
        session.setAttribute("age", "");
        request.setAttribute("urlAction", (String)params.get("urlControleur"));
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }
  • خط ۴: جلسه فعلی در صورت وجود بازیابی می‌شود، و در غیر این صورت ایجاد می‌گردد (پارامتر true از getSession).
  • خطوط ۹–۱۰: نمای [formulaire] نمایش داده می‌شود. به یادآوری، قالب مورد انتظار این نما عبارت است از:

<%
    // بازیابی داده‌ها از مدل
  String nom=(String)session.getAttribute("nom");
  String age=(String)session.getAttribute("age");
  String urlAction=(String)request.getAttribute("urlAction");
%>
  • خطوط ۶–۷: عناصر [nom,age] از قالب نما [formulaire] با رشته‌های خالی مقداردهی اولیه شده و در جلسه قرار می‌گیرند، زیرا این همان جایی است که نما انتظار دارد.
  • خط ۸: عنصر [urlAction] مدل با مقدار پارامتر [urlControleur] از فایل [web.xml] مقداردهی اولیه شده و در پرس‌وجو قرار می‌گیرد.

6.6.5. روش [doValidationFormulaire]

این متد درخواست شمارهٔ ۲، [POST /personne2/main]، را پردازش می‌کند که در آن پارامترهای ارسال‌شده [action, txtNom, txtAge] هستند. کد آن به شرح زیر است:

     //اعتبارسنجی فرم
    void doValidationFormulaire(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);
         // بررسی پارامترها
        ArrayList<String> erreursAppel = new ArrayList<String>();
         // نام نباید خالی باشد
        nom = nom.trim();
        if (nom.equals(""))
            erreursAppel.add("Le champ [nom] n'a pas été rempli");
         //سن باید یک عدد صحیح ≥ 0 باشد
        if (!age.matches("^\\s*\\d+\\s*$"))
            erreursAppel.add("Le champ [age] est erroné");
         //آیا خطایی در پارامترها وجود دارد؟
        if (erreursAppel.size() != 0) {
             //ارسال صفحه خطا
            request.setAttribute("erreurs", erreursAppel);
            request.setAttribute("lienRetourFormulaire", (String)params.get("lienRetourFormulaire"));
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
            return;
        }
         // پارامترها صحیح هستند – صفحه پاسخ ارسال می‌شود
        request.setAttribute("nom", nom);
        request.setAttribute("age", age);
        request.setAttribute("lienRetourFormulaire", (String)params.get("lienRetourFormulaire"));
        getServletContext().getRequestDispatcher((String)params.get("urlReponse")).forward(request,
                response);
        return;
    }
  • خطوط ۵–۶: مقادیر پارامترهای «txtNom» و «txtAge» از درخواست کلاینت بازیابی می‌شوند.
  • خطوط ۸–۱۰: این مقادیر در جلسه (session) ذخیره می‌شوند تا زمانی که کاربر روی لینک [Retour au formulaire] در نماهای [réponse] و [erreurs] کلیک می‌کند، قابل بازیابی باشند.
  • خطوط ۱۲–۱۹: اعتبار مقادیر دو پارامتر بررسی می‌شود
  • خطوط ۲۱–۲۸: اگر هر یک از پارامترها نادرست باشد، نما [erreurs(erreurs,lienRetourFormulaire)] نمایش داده می‌شود. قالب این نما به شرح زیر است:

<%
// بازیابی داده‌ها از قالب
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs"); 
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
  • خطوط ۳۰–۳۴: اگر هر دو پارامتر «txtNom» و «txtAge» که بازیابی شده‌اند مقادیر معتبر داشته باشند، نما [reponse(nom,age,lienRetourFormulaire)] نمایش داده می‌شود. مهم است که قالب نما [reponse] را در نظر داشته باشیم:

<%
    //بازیابی داده‌ها از قالب
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>

6.6.6. متد [doRetourFormulaire]

این روش درخواست شماره ۳، [GET /personne2/main?action=retourFormulaire] را پردازش می‌کند. کد آن به شرح زیر است:

//نمایش فرم از پیش پرشده
    void doRetourFormulaire(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         //بازیابی جلسهٔ کاربر
        HttpSession session = request.getSession(true);        
         //آماده‌سازی قالب فرم
         //آیا نام در جلسه موجود است؟
        String nom = (String) session.getAttribute("nom");
        if (nom == null)
            session.setAttribute("nom", "");
         //آیا سن در جلسه موجود است؟
        String age = (String) session.getAttribute("age");
        if (age == null)
            session.setAttribute("age", "");
         //urlAction
        request.setAttribute("urlAction", (String)params.get("urlControleur"));
         // نمایش فرم
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

پس از تکمیل این روش، نما [formulaire] باید نمایش داده شود، در حالی که با آخرین ورودی‌های کاربر از پیش پر شده است. قالب نما [formulaire] را به یاد آورید:


<%
    // استخراج داده‌ها از مدل
  String nom=(String)session.getAttribute("nom");
  String age=(String)session.getAttribute("age");
  String urlAction=(String)request.getAttribute("urlAction");
%>

بنابراین متد [doRetourFormulaire] باید مدل قبلی را بسازد.

  • خط ۴: ما جلسه‌ای را بازیابی می‌کنیم که در آن کنترل‌کننده مقادیر واردشده (نام، سن) را ذخیره کرده است.
  • خط ۷: نام از جلسه بازیابی می‌شود
  • خطوط ۸–۹: اگر نام وجود نداشته باشد، آن را با یک مقدار خالی اضافه می‌کنیم. این سناریو نباید در حین عملکرد عادی برنامه رخ دهد، زیرا اقدام [retourFormulaire] همیشه پس از اقدام [validationFormulaire] انجام می‌شود، که آن نیز به نوبه خود پس از ذخیره شدن داده‌های وارد شده در جلسه رخ می‌دهد. با این حال، یک جلسه ممکن است منقضی شود زیرا عمر محدودی دارد، که اغلب چند ده دقیقه است. در این حالت، خط ۴ یک جلسه جدید ایجاد کرده است که در آن نام پیدا نخواهد شد. بنابراین یک نام خالی در جلسه جدید تنظیم می‌شود.
  • خطوط ۱۱–۱۳: همین رویه برای سن نیز دنبال می‌شود
  • اگر مسئله منقضی شدن جلسه را نادیده بگیریم، خطوط ۳ تا ۱۳ غیرضروری هستند. عناصر [nom,age] مدل از قبل در جلسه وجود دارند. بنابراین نیازی به افزودن مجدد آنها نیست.
  • خط ۱۵: مقدار عنصر [urlAction] در قالب تنظیم می‌شود

6.7. Tests

تام‌کت را راه‌اندازی یا مجدداً راه‌اندازی کنید. URL [http://localhost:8080/personne2] را درخواست کنید، سپس تست‌های نشان‌داده‌شده به‌عنوان مثال در بخش 6.1 را تکرار کنید.