3. معالجة النموذج بواسطة وحدة التحكم
سنركز الآن على كيفية معالجة وحدة التحكم لقيم النموذج عندما ينقر المستخدم على زر [إرسال] في النموذج.
3.1. ملف struts-config.xml
يبدو ملف التكوين struts-config.xml الجديد لوحدة التحكم Struts كما يلي:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean
name="frmPersonne"
type="istia.st.struts.personne.FormulaireBean"
/>
</form-beans>
<action-mappings>
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/erreurs"
parameter="/vues/erreurs.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/reponse"
parameter="/vues/reponse.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/formulaire"
parameter="/vues/formulaire.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
<message-resources parameter="ressources.personneressources"/>
</struts-config>
لقد قمنا بتمييز التغييرات:
- يظهر قسم <form-beans>. ويُستخدم هذا القسم لتعريف الفئات المرتبطة بكل نموذج من نماذج التطبيق. يجب أن يكون عدد علامات <form-bean> مساوياً لعدد النماذج المختلفة في التطبيق. هنا، لدينا نموذج واحد فقط، لذا يوجد قسم <form-bean> واحد فقط. لكل نموذج، يجب أن نحدد:
- اسمه (سمة name)
- اسم الفئة المشتقة من ActionForm المسؤولة عن تخزين قيم النموذج (السمة type)
لا يمكن أن تكون هاتان السمتان عشوائيتين. يجب أن تتطابقا مع تلك المستخدمة في علامة <html:form> في كود HTML للنموذج. تذكر كود نموذج (name, age):
يجب الإعلان عن النموذج بنفس الطريقة في ملف struts-config.html. وهذا ما يتم هنا:
- لقد تغيرت تهيئة الإجراء /main. هذا الإجراء مسؤول عن معالجة قيم النموذج. لذلك، يجب أن نوفر المعلومات التي يحتاجها عن النموذج:
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
سيقوم سيرفلت /main بمعالجة نموذج، والذي يجب تسميته. تتولى السمة name هذه المهمة. يجب أن يشير هذا الاسم إلى السمة name لأحد أقسام <form-bean>، وفي هذه الحالة frmPersonne.
تشير السمة scope="session" إلى أنه يجب تخزين قيم النموذج في الجلسة. وهذا ليس ضروريًا دائمًا. ولكنه ضروري هنا. في الواقع، في عرضي /reponse.do و /erreurs.do، نجد روابط تعيدنا إلى النموذج. وفي كلتا الحالتين، نريد عرض النموذج بالقيم التي أدخلها المستخدم خلال تبادل سابق بين العميل والخادم. ومن هنا تأتي الحاجة إلى تخزين النموذج في الجلسة.
تشير السمة validate إلى ما إذا كان يجب استدعاء طريقة validate الخاصة بكائن frmPersonne أم لا. تُستخدم هذه الطريقة للتحقق من صحة بيانات النموذج. هنا، نحدد أنه يجب التحقق من البيانات، مما يعني أننا سنحتاج إلى كتابة طريقة validate في فئة FormulaireBean. يتم استدعاء طريقة validate الخاصة بالنموذج بواسطة وحدة التحكم Struts قبل استدعاء السيرفلت /main. وهي تُرجع كائن ActionErrors، وهو ما يعادل قائمة الأخطاء. إذا كانت هذه القائمة موجودة وليست فارغة، فستتوقف وحدة التحكم Struts عند هذا الحد وترسل العرض المحدد بواسطة السمة input كاستجابة. ستتلقى طريقة العرض قائمة ActionErrors في الطلب، والتي يمكنها عرضها باستخدام العلامة <html:errors>. أعلاه، نحدد أنه في حالة وجود أخطاء، يجب أن ترسل خدمة /main طريقة العرض /errors.do. تذكر أن طريقة العرض هذه مرتبطة بعنوان URL التالي: /views/errors.response.jsp:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Les erreurs suivantes se sont produites</h2>
<html:errors/>
<html:link page="/formulaire.do">
Retour au formulaire
</html:link>
</body>
</html>
تستخدم طريقة العرض علامة <html:errors> بشكل صحيح، والتي ستعرض قائمة الأخطاء. في قائمة الأخطاء هذه، لن تجد رسائل خطأ بل معرفات الرسائل الموجودة في الملف المشار إليه بواسطة علامة <message-resources> (ملاحظة: الموارد بـ "s" واحدة):
تشير العلامة أدناه إلى أن الملف الذي يحتوي على الرسائل المستخدمة من قبل التطبيق موجود في الملف WEB-INF/classes/ressources/personneressources.properties:

ماذا يوجد في هذا الملف؟ إنه ملف خصائص يتوافق مع فئة Java Properties، أي مجموعة من الأسطر التي تتكون من مفتاح=قيمة:
errors.header=<ul>
errors.footer=</ul>
personne.formulaire.nom.vide=<li>Vous devez indiquer un nom</li>
personne.formulaire.age.incorrect=<li>L'âge [{0}] est incorrect</li>
يحتوي ملف الرسائل هذا على وظيفتين على الأقل:
- يسمح لك بتغيير رسائل التطبيق دون الحاجة إلى إعادة تجميعه
- ويتيح تدويل تطبيقات Struts. يمكنك إنشاء ملفات موارد متعددة، ملف لكل لغة. سيستخدم Struts تلقائيًا ملف الرسائل الصحيح شريطة اتباع قواعد تسمية معينة.
- إذا عادت طريقة validate الخاصة بالنموذج بقائمة أخطاء فارغة، فإن وحدة التحكم Struts تستدعي طريقة execute الخاصة بـ servlet ForwardAction. من المهم أن نفهم هنا أنه عندما يتم تشغيل طريقة execute الخاصة بـ servlet، فهذا يعني أن بيانات النموذج قد اعتُبرت صالحة (بشرط، بالطبع، أن يتم التحقق من صحتها عبر validate="true"). يقوم المطور فعليًا بمعالجة النموذج ضمن طريقة execute الخاصة بـ servlet المرتبطة بالإجراء. هذا هو المكان الذي يتم فيه جوهر المعالجة (منطق التطبيق، واستخدام فئات الأعمال وفئات الوصول إلى البيانات). في النهاية، تُرجع الطريقة كائن ActionForward الذي يُخبر العارض بالعرض الذي يجب إرساله إلى العميل. هنا استخدمنا الإجراء ForwardAction المُعرَّف مسبقًا في Struts. تُرجع طريقة execute الخاصة به ببساطة كائن ActionForward يشير إلى عنوان URL المحدد بواسطة سمة المعلمة:
<action
path="/main"
name="frmPersonne"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
لذا، إذا كانت بيانات النموذج صالحة، فستُرجع الإجراء /main طريقة العرض /vues/main.html التي استخدمناها بالفعل.
3.2. فئة FormBean الجديدة
لقد أنشأنا بالفعل نسخة أولية من فئة FormBean المسؤولة عن تخزين البيانات (الاسم والعمر) من النموذج formulaire.personne.jsp. لم تقم هذه النسخة بالتحقق من صحة البيانات. الآن، يجب أن نقوم بذلك لأننا حددنا في ملف struts-config.xml أنه يجب التحقق من صحة بيانات النموذج (validate="true") قبل تمريرها إلى سيرفلت ForwardAction. يصبح كود الفئة كما يلي:
package istia.st.struts.personne;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class FormulaireBean
extends ActionForm {
// name
private String nom = null;
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
// age
private String age = null;
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
// validation
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
// error management
ActionErrors erreurs = new ActionErrors();
// name must be non-empty
if (nom == null || nom.trim().equals("")) {
erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide"));
// age must be a positive integer
}
if (age == null || age.trim().equals("")) {
erreurs.add("agevide", new ActionError("personne.formulaire.age.vide"));
}
else {
// age must be a positive integer
if (!age.matches("^\\s*\\d+\\s*$")) {
erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age));
// return the list of errors
}
} //if
// return the error list
return erreurs;
}
}
تكمن الميزة الجديدة في تنفيذ طريقة validate. يتم استدعاء هذه الطريقة بواسطة وحدة التحكم Struts بعد أن تقوم بتعبئة سمات name و age للفئة بالقيم المأخوذة من حقول النموذج التي تحمل نفس الاسم. ويجب عليها التحقق من صحة سمات name و age. الكود أعلاه بسيط إلى حد ما:
- يتم إنشاء قائمة أخطاء فارغة (ActionErrors errors)
- يتم فحص حقل الاسم. إذا كان فارغًا، تتم إضافة خطأ إلى قائمة الأخطاء باستخدام طريقة ActionErrors.add("key", ActionError).
- ويتم إجراء الشيء نفسه إذا لم يكن حقل العمر عددًا صحيحًا.
- تُرجع طريقة validate قائمة الأخطاء (ActionErrors errors) إلى وحدة التحكم Struts. إذا كانت errors فارغة أو إذا كانت errors.size() تساوي 0، تعتبر وحدة التحكم أنه لم تكن هناك أخطاء. ثم ستقوم بتنفيذ طريقة execute لفئة Action المرتبطة بالإجراء (type="org.apache.struts.actions.ForwardAction"). وإلا، فستُرجع العرض المرتبط بأخطاء النموذج (input="/errors.do").
تتم إضافة خطأ إلى قائمة ActionErrors باستخدام ActionErrors.add("errorKey", new ActionError("messageKey"[,param0, param1, param2, param3])). تُستخدم المعلمة الأولى، "errorKey"، للتعريف الفريد لعنصر ActionError في قائمة ActionErrors، تمامًا كما هو الحال في القاموس. ويمكن أن تكون أي سلسلة نصية. ActionError هو كائن مرتبط برسالة خطأ باستخدام منشئه ActionError(String errorKey[,String param0, String param1, String param2, String param3])، حيث errorKey هو معرف الرسالة المرتبطة بالخطأ وما يصل إلى 4 معلمات اختيارية. معرف keyMessage ليس عشوائيًا. إنه أحد المعرفات الموجودة في الملف المحدد بواسطة العلامة <message-resources> في ملف struts-config.xml:
لاحظ أن هذا الملف (في الواقع WEB-INF/classes/resources/personneressources.properties) يحتوي على المفاتيح التالية:
errors.header=<ul>
errors.footer=</ul>
personne.formulaire.nom.vide=<li>Vous devez indiquer un nom</li>
personne.formulaire.age.incorrect=<li>L'âge [{0}] est incorrect</li>
يمكننا التحقق من أن مفاتيح الرسائل المستخدمة بواسطة طريقة validate لفئة FormBean موجودة بالفعل في الملف أعلاه. استخدمنا علامة HTML <li> لكل رسالة خطأ بحيث تعرضها علامة <html:errors> كقائمة HTML. لقد رأينا أنه يمكن إنشاء كائن ActionError ليس فقط باستخدام مفتاح رسالة ولكن أيضًا باستخدام معلمات إضافية:
إذا تم إنشاء ActionError بمعلمات إضافية (بحد أقصى أربعة)، فيمكن الوصول إليها في نص الرسالة عبر الترميز {0} إلى {3}. وبالتالي، تقوم طريقة validate الخاصة بـ FormulaireBean بإنشاء ActionError بالمفتاح personne.formulaire.age.incorrect والمعلمة الإضافية param0 age:
الرسالة المرتبطة بالمفتاح **person.form.age.incorrect** في ملف .properties هي
سيتم استبدال {0} بقيمة العمر. وأخيرًا، سيتم كتابة الرسائل ذات المفاتيح errors.header و errors.footer قبل قائمة الأخطاء وبعدها، على التوالي. هنا، سيتم استخدام هذين المفتاحين لتضمين علامات HTML <ul> و </ul>، التي يجب أن تحيط بعلامات <li>.
3.3. اختبارات التحقق من صحة النموذج
نحن جاهزون لاختبار صحة النموذج. فيما يلي تذكير بمكان وضع المكونات المختلفة للتطبيق:
![]() | |
![]() | |
![]() | |
![]() |
3.3.1. الاختبار 1
أعد تشغيل Tomcat حتى يقرأ ملفات التكوين الجديدة، ثم أدخل عنوان URL http://localhost:8080/strutspersonne/formulaire.do:

التفسيرات:
- في struts-config.html، تم استخدام القسم التالي:
<action
path="/formulaire"
parameter="/vues/formulaire.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
إذا قمنا بعرض كود HTML للصفحة المستلمة، نرى أن علامة <form> الموجودة على الصفحة هي كما يلي:
وبالتالي، فإن زر [Submit]، الذي ينتمي إلى نوع submit، سيرسل بيانات النموذج إلى عنوان URL /strutspersonne/main.do.
3.3.2. الاختبار 2
دعونا نستخدم زر [Submit] مع ترك حقول الإدخال فارغة. نحصل على الاستجابة التالية:

التفسيرات:
- كما هو موضح أعلاه، تم إرسال بيانات النموذج إلى عنوان URL /strutspersonne/main.do. ثم تم استخدام الأقسام التالية من ملف struts-config.xml:
<form-bean
name="frmPersonne"
type="istia.st.struts.personne.FormulaireBean"
scope="session"
/>
....
<action
path="/main"
name="frmPersonne"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
تم تشغيل الإجراء /main. وهو يستخدم نموذج frmPersonne (name="frmPersonne"). وبالتالي، قام وحدة التحكم Struts بإنشاء مثيل، إذا لزم الأمر، لكائن من فئة FormulaireBean (type="istia.st.struts.personne.FormulaireBean" في علامة form-bean). وقام بتعبئة سمات الاسم والعمر لهذا الكائن باستخدام الحقول التي تحمل نفس الاسم في النموذج HTML:
<table>
<tr>
<td>Nom</td>
<td><html:text property="nom" size="20"/></td>
</tr>
<tr>
<td>Age</td>
<td><html:text property="age" size="3"/></td>
</tr>
<tr>
</table>
بمجرد الانتهاء من ذلك، يقوم وحدة التحكم Struts باستدعاء طريقة validate الخاصة بكائن FormBean لأن السمة validate الخاصة بعملية /main تم تعيينها على true في ملف التكوين:
<action
path="/main"
name="frmPersonne"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
طريقة validate لفئة FormBean هي كما يلي:
// validation
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
// error management
ActionErrors erreurs = new ActionErrors();
// name must be non-empty
if (nom == null || nom.trim().equals("")) {
erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide"));
// age must be a positive integer
}
if (age == null || age.trim().equals("")) {
erreurs.add("agevide", new ActionError("personne.formulaire.age.vide"));
}
else {
// age must be a positive integer
if (!age.matches("^\\s*\\d+\\s*$")) {
erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age));
// return the list of errors
}
} //if
// return the error list
return erreurs;
}
نظرًا لأن الحقلين [name] و [age] كانا فارغين، فقد أنشأت طريقة validate المذكورة أعلاه قائمة من خطأين، وأعادتها إلى وحدة التحكم Struts. ونظرًا لوجود أخطاء، أعادت وحدة التحكم بعد ذلك العرض المرتبط بسمة الإدخال إلى العميل. ولتحديد أي عرض كان هذا، استخدمت القسم التالي من ملف التكوين الخاص بها:
<action
path="/erreurs"
parameter="/vues/erreurs.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
وبالتالي، أرسل في النهاية العرض /views/errors.person.jsp. يحتوي هذا العرض على الكود التالي:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Les erreurs suivantes se sont produites</h2>
<html:errors/>
<html:link page="/formulaire.do">
Retour au formulaire
</html:link>
</body>
</html>
تعرض علامة <html:errors> ببساطة قائمة الرسائل المرسلة إليها من قبل وحدة التحكم Struts. وهي تستخدم ملف الرسائل المحدد بواسطة علامة <message-resources>:
وهي تحتوي على المفاتيح والرسائل التالية:
personne.formulaire.nom.vide=<li>Vous devez indiquer un nom</li>
personne.formulaire.age.vide=<li>Vous devez indiquer un age</li>
personne.formulaire.age.incorrect=<li>L'âge [{0}] est incorrect</li>
errors.header=<ul>
errors.footer=</ul>
- يتم كتابة الرسالة المرتبطة بمفتاح errors.header
- يتم كتابة الرسائل المرتبطة بالمفاتيح المختلفة في قائمة ActionErrors المستلمة
- يتم كتابة الرسالة المرتبطة بمفتاح errors.footer
3.3.3. الاختبار 3
دعونا نستخدم رابط [العودة إلى النموذج] الموجود في صفحة الخطأ. نحصل على الصفحة التالية:

التفسيرات:
- يحتوي رابط [العودة إلى النموذج] على كود HTML التالي:
استخدمت وحدة التحكم Struts القسم التالي من ملف التكوين الخاص بها:
<action
path="/formulaire"
parameter="/vues/formulaire.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
وبالتالي، فقد أعاد العرض /views/form.person.jsp.
3.3.4. الاختبار 4
نملأ النموذج التالي ثم نضغط على زر [إرسال]:

نحصل على الرد التالي:

التفسيرات: هذه هي نفس التفسيرات الخاصة بالاختبار 2.
3.3.5. الاختبار 5
نضغط على رابط [العودة إلى النموذج] أعلاه. تظهر لنا الصفحة التالية:

نرى أن النموذج في نفس الحالة التي كان عليها عند إرساله.
التفسيرات: هذه هي نفس التفسيرات الخاصة بالاختبار رقم 3، مع معلومات إضافية:
- يحتوي النموذج HTML المعروض على العلامات التالية:
<table>
<tr>
<td>Nom</td>
<td><html:text property="nom" size="20"/></td>
</tr>
<tr>
<td>Age</td>
<td><html:text property="age" size="3"/></td>
</tr>
<tr>
</table>
تتمتع علامات <html:text> بوظيفتين:
- عند إرسال قيم النموذج من العميل إلى الخادم، يتم تعيين قيم حقول الإدخال في النموذج إلى الحقول التي تحمل الاسم نفسه في كائن FormBean
- عندما يرسل الخادم كود HTML الخاص بالنموذج المراد عرضه مرة أخرى إلى العميل، يتم تهيئة سمات القيمة لحقول الإدخال المرتبطة بعلامات <html:text> بقيم الحقول التي تحمل نفس الاسم في كائن FormBean.
هنا لدينا تفاعلان مختلفان بين العميل والخادم:
- في الأول، قام المستخدم بملء النموذج وإرساله إلى الخادم
- في الحالة الثانية، نقر المستخدم على رابط [العودة إلى النموذج] للعودة إلى النموذج.
الطريقة الوحيدة لإعادة عرض النموذج بقيمه الأصلية في التفاعل الثاني هي تخزين تلك القيم في جلسة عمل العميل. وهذا ما تم تحديده في القسم الخاص بتكوين الإجراء /main:
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
لو كنا قد حددنا scope="request"، لما تم تخزين بيانات النموذج في الجلسة، ولما تمكنا من استرداد قيمها في التبادل الثاني.
3.3.6. الاختبار 6
لنعد إلى النموذج وندخل بيانات صالحة هذه المرة:

أرسل النموذج. نحصل على النتيجة التالية:

التفسيرات:
- نظرًا لأن زر [إرسال] يرسل قيم النموذج إلى عنوان URL /strutspersonne/main.do، فإن نفس التفسيرات الموضحة في الاختبار 2 تنطبق حتى يتلقى وحدة التحكم Struts نتيجة ActionErrors من طريقة validate الخاصة بـ FormBean. ولكن هنا، هذه القائمة فارغة. ثم تستخدم وحدة التحكم جزءًا جديدًا من تكوين الإجراء /main:
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
يقوم وحدة التحكم Struts بإنشاء كائن من النوع المحدد بواسطة السمة type، إذا لزم الأمر. يتم تنفيذ طريقة execute لهذه الفئة ويجب أن ترجع كائن ActionForward يشير إلى العرض الذي يجب على وحدة التحكم إرساله كاستجابة للعميل. هنا، تشير السمة type إلى فئة ForwardAction المحددة مسبقًا. لا تقوم طريقة execute لهذه الفئة بأي شيء، بل تعيد ببساطة كائن ActionForward يشير إلى العرض المحدد بواسطة السمة parameter، وهو في هذه الحالة العرض /vues/main.html. وهذا هو بالفعل العرض الذي أعادته وحدة التحكم.
3.3.7. الاختبار 7
نطلب عرض /form.do مرة أخرى:

نرى النموذج تمامًا كما أرسلناه. وقد تم تقديم التفسير بالفعل. من خلال التكوين (scope="session")، حددنا أن النموذج يجب أن يبقى في الجلسة. وبالتالي، يتم الاحتفاظ بقيمه طوال عمليات التبادل بين العميل والخادم.
لقد أوشكنا على الانتهاء. ما زلنا بحاجة إلى إنشاء إجراء مناسب عندما تكون بيانات النموذج صالحة. في الوقت الحالي، استخدمنا ForwardAction المحددة مسبقًا لتبسيط عرضنا التوضيحي.
3.4. تكوين جديد للإجراء /main
لن نقوم بتغيير ملف التكوين struts-config.xml الحالي، باستثناء تعديل قسم /main فيه على النحو التالي:
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
type="istia.st.struts.personne.FormulaireAction"
>
<forward name="reponse" path="/reponse.do"/>
</action>
تشير السمة type الآن إلى فئة أخرى تسمى FormAction، والتي سنحتاج إلى تنفيذها. إن طريقة execute لهذه الفئة هي التي سيتم استدعاؤها إذا كانت البيانات الموجودة في النموذج frmPersonne صالحة. لقد حددنا أن طريقة execute تؤدي مهمتها وتُرجع كائن ActionForward يشير إلى العرض الذي يجب على وحدة التحكم إرساله إلى العميل. غالبًا ما تكون هناك عدة عروض ممكنة اعتمادًا على نتيجة معالجة النموذج. يتم تحديد قائمة العروض الممكنة داخل علامات <forward> المضمنة في علامة <action>. صيغة هذه العلامة هي كما يلي:
أي اسم يحدد طريقة العرض بشكل فريد | |
عنوان URL للعرض المرتبط بالمفتاح |
3.5. فئة FormAction
تتكون كتابة فئة FormAction أساسًا من كتابة طريقة execute الخاصة بها:
package istia.st.struts.personne;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import javax.servlet.ServletException;
public class FormulaireAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException,ServletException {
// we have a valid form, otherwise we wouldn't have got here
FormulaireBean formulaire=(FormulaireBean)form;
request.setAttribute("nom",formulaire.getNom());
request.setAttribute("age",formulaire.getAge());
return mapping.findForward("reponse");
}//execute
}
تأخذ طريقة execute أربعة معلمات:
- ActionMapping mapping: كائن "image" يمثل تكوين الإجراء الذي يتم تنفيذه حاليًا؛ في هذه الحالة، صورة للتكوين التالي:
<action
path="/main"
name="frmPersonne"
validate="true"
input="/erreurs.do"
type="istia.st.struts.personne.FormulaireAction"
>
<forward name="reponse" path="/reponse.do"/>
</action>
وبالتالي، فإن الإجراء لديه حق الوصول إلى المفاتيح المرتبطة بالطرق التي يمكن إرجاعها إلى العميل في نهاية الإجراء. يجب أن ترجع طريقة execute أحد هذه المفاتيح.
- ActionForm form: كائن bean الذي يحتوي على قيم النموذج المستخدمة من قبل الإجراء الحالي. هنا، هو كائن frmPersonne من نوع FormBean. وبالتالي، فإن الإجراء لديه حق الوصول إلى قيم النموذج.
- HttpServletRequest request: طلب العميل، الذي قد يكون تم إثرائه بواسطة سيرفلتات مختلفة. وبالتالي، فإن الإجراء لديه حق الوصول إلى جميع معلمات الطلب الأولي (request.getParameter) بالإضافة إلى جميع السمات المضافة إلى ذلك الطلب الأولي (request.getAttribute). في مثالنا، تُثري طريقة execute الطلب بإضافة الاسم والعمر. وهذا غير ضروري تمامًا هنا لأن هاتين القيمتين موجودتان بالفعل، ولكن كمعلمات وليس كسمات. تم تضمين الكود هنا لأغراض توضيحية.
- HttpServletResponse response: الاستجابة التي سيتم إرسالها إلى العميل. يمكن للإجراء إثراء هذه الاستجابة. هنا، لا يفعل ذلك.
هنا، نحن نتعامل مع حالة خاصة. لا يوجد ما تفعله طريقة execute تقريبًا. إنها تحتاج ببساطة إلى الإشارة إلى أن العرض التالي هو /reponse.do وتحديد في الطلب أن هذا العرض سيتلقى معلومات الاسم والعمر التي يحتاجها للعرض. وهي تقوم بذلك باستخدام طريقة findForward لفئة ActionMapping، والتي تأخذ كمعلمة أحد المفاتيح الموجودة في علامات التوجيه في تكوين الإجراء. هنا، توجد علامة واحدة فقط من هذا النوع:
وبالتالي، تُرجع طريقتنا ActionForward مع "response" كمفتاح للإشارة إلى أنه يجب إرسال عرض /response.do.
3.6. اختبارات FormAction
نقوم بتجميع الفئة السابقة باستخدام JBuilder ونضع ملف .class الذي تم إنشاؤه في WEB-INF/classes:

نقوم بتعديل العرض /vues/reponse.personne.jsp:
<%
// on récupère les données nom, age
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
%>
<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>
<html:link page="/formulaire.do">
Retour au formulaire
</html:link>
</body>
</html>
تسترد طريقة العرض معلومات الاسم والعمر من سمات الطلب التي تتلقاها. نطلب النموذج على عنوان URL http://localhost:8080/strutspersonne/formulaire.do ثم نملؤه:

نضغط على زر [إرسال] ونتلقى الرد التالي:

التفسيرات:
- سنرجع إلى التفسير المقدم للاختبار رقم 2 فيما يتعلق ببداية العملية. دعونا نراجع تكوين الإجراء /main:
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
type="istia.st.struts.personne.FormulaireAction"
>
<forward name="reponse" path="/reponse.do"/>
</action>
- بعد إرسال النموذج إلى وحدة التحكم على عنوان URL /main.do، قامت وحدة التحكم بإنشاء أو إعادة استخدام كائن frmPersonne من نوع FormBean وملأته بقيم النموذج
- تم استدعاء طريقة validate الخاصة بكائن frmPersonne. ونظرًا لأن البيانات كانت صالحة، فقد عادت طريقة validate بقائمة ActionErrors فارغة.
- تم إنشاء كائن FormAction أو إعادة استخدامه، وتم استدعاء طريقة execute الخاصة به. أعادت هذه الطريقة كائن ActionForward بالمفتاح "reponse".
- ثم أرسل وحدة التحكم العرض المرتبط بالمفتاح "reponse"، أي /reponse.do، وبالتالي /vues/reponse.personne.jsp.
- تم عرض العرض reponse.personne.jsp بالقيم التي تم تعيينها في الطلب بواسطة طريقة execute الخاصة بكائن FormAction.
3.7. الخلاصة
لقد قمنا بإنشاء تطبيق شامل وبسيط في الوقت نفسه. وعند تنفيذه فعليًا باستخدام Struts وTomcat وJBuilder، توجد العديد من الفرص لارتكاب الأخطاء، لا سيما في ملفات تكوين XML الخاصة بالتطبيق. للوهلة الأولى، قد يبدو إنشاء هذا التطبيق بدون Struts، باستخدام سيرفلت وصفحات JSP، أسهل. وبالنسبة للمبتدئين، ربما يكون هذا صحيحًا. ومع اكتساب الخبرة، يصبح التطوير باستخدام Struts أسهل. تفرض العديد من الشركات منهجية Struts لتطوير الويب لديها للأسباب التالية:
- تلتزم Struts بنموذج MVC
- عندما يعمل جميع المطورين بنفس الطريقة، تصبح صيانة التطبيق أسهل لأنهم يستخدمون بنية قياسية.



