7. تطبيق الويب MVC [personne] – الإصدار 3
قراءات موصى بها في [ref1]: الفصل 9
7.1. مقدمة
نقترح إضافة كود جافا سكريبت إلى الصفحات HTML المرسلة إلى المتصفح. يقوم المتصفح بتنفيذ كود جافا سكريبت المضمن في الصفحة التي يعرضها. هذه التقنية مستقلة عن تلك المستخدمة من قبل خادم الويب لإنشاء المستند HTML (Java/servlets/JSP، ASP.NET، ASP، PHP، Perl، Python، ...).
[formulaire.jsp]
سيكون شكل العرض الناتج عن هذه الصفحة كما يلي:

الأزرار التي تظهر تسميتها داخل إطار تستخدم كود جافا سكريبت مدمج في الصفحة HTML:
التسمية | النوع HTML | الوظيفة |
<submit> | يلعب دور الزر [Envoyer] في الإصدارات السابقة: يرسل القيم المدخلة إلى وحدة التحكم | |
<button> | زر جديد – يتحقق محليًا من صحة البيانات المدخلة قبل إرسالها إلى وحدة التحكم | |
<reset> | يعيد النموذج إلى الحالة التي استلمه بها المتصفح في البداية | |
<button> | يمسح محتوى حقلَي الإدخال |
فيما يلي مثال على استخدام الأزرار [Envoyer] و [Effacer]:
![]() | ![]() |
![]() | ![]() |
سنستخدم أيضًا كود جافا سكريبت لإدارة الرابط [Retour au formulaire] الخاص بعروض [erreurs] و [réponse]. لنأخذ عرض [réponse] كمثال:
![]() | 1 ![]() |
يكمن الاختلاف في عنوان URL المعروض في [1]. في الإصدار السابق، كان العنوان كما يلي:
هنا، لم تعد الإجراء جزءًا من عنوان URL لأنه سيتم إرساله بواسطة POST بدلاً من GET. سيؤدي هذا التعديل إلى أن يكون عنوان URL الوحيد الذي يعرضه المتصفح هو [http://localhost:8080/personne3/main] بغض النظر عن الإجراء المطلوب.
7.2. مشروع Eclipse
لإنشاء مشروع Eclipse [mvc-personne-03] لتطبيق الويب [/personne3]، سنقوم بنسخ مشروع [mvc-personne-02] باتباع الإجراء الموضح في الفقرة 6.2، صفحة 78.
![]() | ![]() |
7.3. تكوين تطبيق الويب [personne3]
الملف web.xml لتطبيق /personne3 هو التالي:
<?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-03</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>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>
هذا الملف مطابق لملف الإصدار السابق باستثناء بعض التفاصيل:
- السطر 6: تغير اسم عرض تطبيق الويب إلى [mvc-personne-03]
اختفى المعلمة [urlControleur]. في الإصدار السابق، كانت تُستخدم لتحديد هدف POST من العرض [formulaire]. في هذا الإصدار الجديد، سيكون الهدف هو السلسلة الفارغة، c.a.d. عنوان URL المعروض في المتصفح. وقد أوضحنا أن هذا العنوان سيظل دائمًا [http://localhost:8080/personne3/main]، وهو العنوان الذي نحتاجه لـ POST في عرض [formulaire].
تتغير الصفحة الرئيسية [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("/personne3/main");
%>
- السطر 5: الصفحة [index.jsp] تعيد توجيه العميل إلى عنوان URL لوحدة التحكم [ServletPersonne] للتطبيق [/personne3].
7.4. كود العروض
7.4.1. عرض [formulaire]
أصبحت هذه العرض كما يلي:

يتم إنشاؤها بواسطة الصفحة التالية 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");
%>
<html>
<head>
<title>Personne - formulaire</title>
<script language="javascript">
// -------------------------------
function effacer(){
// مسح حقول الإدخال
with(document.frmPersonne){
txtNom.value="";
txtAge.value="";
}//مع
}//مسح
// -------------------------------
function envoyer(){
// التحقق من المعلمات قبل إرسالها
with(document.frmPersonne){
// يجب ألا يكون الاسم فارغًا
champs=/^\s*$/.exec(txtNom.value);
if(champs!=null){
// الاسم فارغ
alert("Vous devez indiquer un nom");
txtNom.value="";
txtNom.focus();
// العودة إلى الواجهة المرئية
return;
}//if
// يجب أن يكون العمر عددًا صحيحًا موجبًا
champs=/^\s*\d+\s*$/.exec(txtAge.value);
if(champs==null){
// العمر غير صحيح
alert("Age incorrect");
txtAge.focus();
// العودة إلى الواجهة المرئية
return;
}//if
// المعلمات صحيحة - يتم إرسالها إلى الخادم
submit();
}//مع
}//إرسال
</script>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form name="frmPersonne" 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="Submit"></td>
<td><input type="button" value="[Envoyer]" onclick="envoyer()"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="button" value="[Effacer]" onclick="effacer()"></td>
</tr>
</table>
<input type="hidden" name="action" value="validationFormulaire">
</form>
</center>
</body>
</html>
المستجدات:
- السطر 56: النموذج له اسم [frmPersonne]. سيتم استخدام هذا الاسم في كود جافا سكريبت. يُلاحظ غياب السمة [action] مما يعني أن النموذج [frmPersonne] سيتم إرساله إلى عنوان URL المعروض في المتصفح.
- السطر 70: يؤدي الزر [Submit] دور الزر [Envoyer] في الإصدارات السابقة
- السطر 71: يؤدي النقر على الزر [Envoyer] من النوع [Button] إلى تنفيذ وظيفة جافا سكريبت [envoyer] المحددة في السطر 24
- السطر 72: لم تتغير وظيفة الزر [Rétablir]
- السطر 73: يؤدي النقر على الزر [Effacer] من النوع [Button] إلى تنفيذ وظيفة جافا سكريبت [effacer] المحددة في السطر 16
قبل التعليق على كود جافا سكريبت، دعونا نذكر بعض الملاحظات:
يدير جافا سكريبت الصفحة المعروضة ومحتواها كشجرة من الكائنات التي جذرها هو الكائن [document]. في هذا المستند، قد يكون هناك نموذج واحد أو أكثر. يشير [document.frmPersonne] إلى النموذج المسمى [frmPersonne] المحدد في السطر 56. يحتوي هذا النموذج أيضًا على كائنات. وتعد حقول الإدخال جزءًا منها. وبالتالي، يشير [document.frmPersonne.txtNom] إلى كائن الصورة الخاص بحقل الإدخال HTML المحدد في السطر 60. يحتوي الكائن [txtNom] على خصائص متنوعة، منها الخاصية [value] التي تشير إلى محتوى حقل الإدخال. وبالتالي، يشير [document.frmPersonne.txtNom.value] إلى محتوى حقل الإدخال [txtNom].
- الأسطر 16-22: تضع دالة جافا سكريبت [effacer] سلسلة فارغة في حقول الإدخال [txtNom, txtAge].
- الأسطر 24-49: تتحقق وظيفة جافا سكريبت [envoyer] من صحة قيم حقول الإدخال [txtNom, txtAge] قبل إرسالها. وتستخدم لهذا الغرض التعبيرات العادية.
- السطر 28: يتحقق مما إذا كانت قيمة حقل الإدخال [txtNom] تتطابق مع النمط /s* الذي يعني 0 أو أكثر من مسافة. إذا كانت الإجابة بنعم، فهذا يعني أن المستخدم لم يحدد اسمًا. إذا كان هناك تطابق مع النموذج، فستكون للمتغير champs قيمة مختلفة عن المؤشر null، وإلا فستكون قيمته null.
- السطر 29: إذا كان هناك تطابق مع النموذج
- السطر 30: يتم عرض رسالة للمستخدم
- السطر 32: يتم وضع سلسلة فارغة في الحقل [txtNom] (قد يكون هناك سلسلة من المسافات)
- السطر 33: يتم وضع المؤشر الوامض على الحقل [txtNom]
- السطر 34: يتم إيقاف الدالة. وبالتالي، لا يوجد POST على الخادم للقيم التي تم إدخالها.
- الأسطر 38-45: نتبع نفس الإجراء مع الحقل [txtAge]
- السطر 47: إذا وصلنا إلى هنا، فهذا يعني أن القيم المدخلة صحيحة. ثم نرسل (submit) النموذج [frmPersonne] إلى خادم الويب. ويحدث كل شيء كما لو أننا ضغطنا على الزر المسمى [Submit].
7.4.2. الطريقة [reponse]
تعرض هذه الصفحة القيم التي تم إدخالها في النموذج عندما تكون صالحة:
![]() | ![]() |
بالمقارنة مع الإصدار السابق، لا تظهر الميزة الجديدة إلا عند استخدام الرابط [Retour au formulaire] من العرض [réponse]:
![]() | ![]() |
يكمن الاختلاف في عنوان URL المعروض في [1]. في الإصدار السابق، كان العنوان كما يلي:
هنا، لم تعد الإجراء جزءًا من عنوان URL لأنه سيتم إرساله بواسطة POST بدلاً من GET. الصفحة الجديدة JSP [reponse.jsp] هي lqqqaaaaaaaaaqqAAAaaa
التالية:
<%@ 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>
<form name="frmPersonne" method="post">
<input type="hidden" name="action" value="retourFormulaire">
</form>
<a href="javascript:document.frmPersonne.submit();">
<%= lienRetourFormulaire %>
</a>
</body>
</html>
المستجدات:
- الأسطر 35-37: الرابط [Retour au formulaire] يحتوي على جافا سكريبت. يؤدي النقر على هذا الرابط إلى تنفيذ كود جافا سكريبت الخاص بالسمة [href]. كما رأينا في دراسة [formulaire.jsp]، نعلم أن هذا الكود يرسل قيم الحقول من النوع <input> و<select>... من النموذج [frmPersonne].
- الأسطر 32-34: تحدد النموذج [frmPersonne]. يحتوي هذا النموذج على حقل واحد من النوع <input type= "hidden " ...>، أي حقل مخفي. يُستخدم هذا الحقل [action] لنقل اسم الإجراء المطلوب تنفيذه إلى وحدة التحكم، وهو هنا [retourFormulaire].
7.4.3. الطريقة [erreurs]
تشير هذه العرضة إلى أخطاء الإدخال في النموذج. التعديل الذي تم إجراؤه هو نفسه الذي تم إجراؤه في العرضة [réponse]:
![]() | ![]() |
يكمن الاختلاف في عنوان URL المعروض في [1]. في الإصدار السابق، كان العنوان كما يلي:
هنا، لم تعد الإجراء جزءًا من عنوان URL لأنه سيتم إرساله بواسطة POST بدلاً من GET. الصفحة الجديدة 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">
<%@ 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>
<form name="frmPersonne" method="post">
<input type="hidden" name="action" value="retourFormulaire">
</form>
<a href="javascript:document.frmPersonne.submit();">
<%= lienRetourFormulaire %>
</a>
</body>
</html>
المستجدات:
- الأسطر 30-32: الإدارة الجديدة للنقر على الرابط. التفسيرات المقدمة حول هذا الموضوع في دراسة [réponse.jsp] تنطبق هنا أيضًا.
7.5. اختبارات العروض
لإجراء اختبارات العروض السابقة، نقوم بنسخ صفحاتها JSP في المجلد /WebContent/JSP من مشروع Eclipse:

ثم في المجلد JSP، يتم تعديل الصفحات على النحو التالي:
[formulaire.jsp]:
...
<%
// -- اختبار: يتم إنشاء قالب الصفحة
session.setAttribute("nom","tintin");
session.setAttribute("age","30");
%>
<%// يتم استرداد بيانات النموذج
String nom = (String) session.getAttribute("nom");
String age = (String) session.getAttribute("age");
%>
تمت إضافة السطور 4-5 لإنشاء النموذج الذي تحتاجه الصفحة في السطور 9-10.
[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");
%>
...
تمت إضافة الأسطر 4-6 لإنشاء القالب الذي تحتاجه الصفحة في الأسطر 11-13.
[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");
%>
تمت إضافة الأسطر 4-8 لإنشاء النموذج الذي تحتاجه الصفحة في الأسطر 13-14.
قم بتشغيل Tomcat إذا لم تكن قد قمت بذلك بالفعل، ثم اطلب العناوين التالية:
![]() | ![]() |
![]() |
نحصل بالفعل على العروض المتوقعة.
7.6. وحدة التحكم [ServletPersonne]
ستقوم وحدة التحكم [ServletPersonne] الخاصة بتطبيق الويب [/personne3] بمعالجة الإجراءات التالية:
رقم | الطلب | الأصل | المعالجة |
1 | [GET /personne3/main] | رابط URL الذي أدخله المستخدم | - إرسال عرض [formulaire] فارغ |
2 | [POST /personne3/main] مع المعلمات [txtNom, txtAge، action=validationFormulaire] المنشورة | النقر على الزر [Envoyer] في العرض [formulaire] | - التحقق من قيم المعلمات [txtNom, txtAge] - إذا كانت غير صحيحة، أرسل العرض [erreurs(erreurs)] - إذا كانت صحيحة، أرسل العرض [reponse(nom,age)] |
3 | [POST /personne3/main] مع المعلمات [action=retourFormulaire] تم حذفها | انقر على الرابط [العودة إلى النموذج] من المشاهدات [réponse] و [erreurs]. | - إرسال العرض [formulaire] مملوء مسبقًا بأحدث القيم التي تم إدخالها |
لذلك لدينا إجراء جديد يجب معالجته: [POST /personne3/main] مع المعلمة المرسلة [action=retourFormulaire]. بدلاً من الإجراء القديم [GET /personne3/main?action=retourFormulaire].
7.6.1. هيكل وحدة التحكم
هيكل وحدة التحكم [ServletPersonne] مطابق للنسخة السابقة.
المستجدات:
- السطر 11، لم يعد الجدول [paramètres] يحتوي على المعلمة [urlControleur] التي تم حذفها من الملف [web.xml].
تظل الطرق [init, doValidationFormulaire] كما هي. تتغير الطرق [doGet, doInit, doRetourFormulaire] بشكل طفيف.
7.6.2. الطريقة [doGet]
يجب أن تعالج الطريقة [doGet] الإجراء [POST /personne3/main] باستخدام المعلمة المرسلة [action=retourFormulaire]:
- الأسطر 6-9: معالجة الإجراء [POST /personne3/main] باستخدام المعلمة المرسلة [action=retourFormulaire]
7.6.3. الطريقة [doInit]
تعالج هذه الطريقة الطلب رقم 1 [GET /personne3/main]. ورمزها هو كما يلي:
الجديد هو أن العرض [formulaire] المعروض في السطر 8 لم يعد يحتوي على العنصر [action] في نموذجه.
7.6.4. الطريقة [doRetourFormulaire]
تعالج هذه الطريقة الطلب رقم 1 [POST /personne3/main] مع [action=retourFormulaire] في العناصر المرسلة. رمزها هو كما يلي:
الجديد هو أن العرض [formulaire] المعروض في السطر 14 لم يعد يحتوي على العنصر [action] في نموذجه.
7.7. الاختبارات
قم بتشغيل أو إعادة تشغيل Tomcat بعد دمج مشروع Eclipse [personne-mvc-03] فيه. اطلب عنوان URL [http://localhost:8080/personne3] ثم استأنف الاختبارات الموضحة في المثال الوارد في الفقرة 7.1.















