6. نماذج HTML
حتى الآن، استخدمنا نموذجًا واحدًا يحتوي على حقلين للإدخال فقط. هنا، نقترح إنشاء ومعالجة نموذج باستخدام مكونات رسومية قياسية (أزرار الاختيار، مربعات الاختيار، حقول الإدخال، مربعات القائمة المنسدلة، القوائم).
6.1. طرق عرض التطبيق
سيكون للتطبيق عرضان فقط. يعرض الأول نموذجًا فارغًا:
العرض 1 - النموذج

ستسمح لنا هذه الواجهة الأولى، المسماة form.jsp، بتنفيذ علامات متنوعة من مكتبة struts-html. يقوم المستخدم بملء النموذج:

يؤكد زر [إرسال] القيم التي تم إدخالها. وسيكون هذا هو العرض الثاني:

ستسمح لنا هذه الشاشة الثانية باستخدام مكتبتين أخريين للعلامات: struts-bean و struts-logic. يتيح لنا الرابط [العودة إلى النموذج] العودة إلى النموذج كما قمنا بملئه. ثم نعود إلى الشاشة الأولى.
6.2. بنية التطبيق
![]() |
- سيتم تمثيل النموذج (الطريقة 1) بواسطة كائن Struts ديناميكي يُسمى dynaFormulaire، وهو فئة فرعية من DynaActionForm. وسيتم عرضه بواسطة طريقة العرض form.jsp.
- وستكون عملية Struts InitFormulaireAction مسؤولة عن استرداد البيانات اللازمة لعرض النموذج
- سيتم معالجة النموذج المكتمل بواسطة ForwardAction، والتي ستقوم ببساطة بإعادة توجيه الطلب إلى العرض الثاني، confirmation.jsp. وسيكون هذا العرض مسؤولاً عن عرض قيم النموذج.
6.3. تكوين التطبيق
6.3.1. ملف server.xml
سيتم تسمية سياق التطبيق بـ /formulaire2. لذلك سنضيف السطر التالي إلى ملف server.xml الخاص بـ Tomcat:
بمجرد الانتهاء من ذلك، قد نحتاج إلى إعادة تشغيل Tomcat حتى يتعرف على السياق الجديد. يمكننا التحقق من صحة ذلك عن طريق طلب عنوان URL http://localhost:8080/formulaire2:

6.3.2. ملف web.xml
سيكون ملف تكوين web.xml الخاص بالتطبيق كما يلي:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
</web-app>
بالمقارنة مع ملفات التكوين web.xml التي رأيناها سابقًا، نقوم بإجراء بعض التغييرات:
- نقدم مكتبتين جديدتين للعلامات: struts-bean و struts-logic. وسيتم استخدامهما في عرض confirmation.jsp. أما عرض formulaire.jsp، فسيستخدم مكتبة struts-html.
6.3.3. ملف struts-config.xml
سيكون ملف struts-config.xml كما يلي:
<?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="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<form-property name="opt" type="java.lang.String" initial="non"/>
<form-property name="chk1" type="java.lang.String"/>
<form-property name="chk2" type="java.lang.String"/>
<form-property name="chk3" type="java.lang.String"/>
<form-property name="champSaisie" type="java.lang.String" initial=""/>
<form-property name="mdp" type="java.lang.String" initial=""/>
<form-property name="boiteSaisie" type="java.lang.String" initial=""/>
<form-property name="combo" type="java.lang.String"/>
<form-property name="listeSimple" type="java.lang.String"/>
<form-property name="listeMultiple" type="java.lang.String[]"/>
<form-property name="secret" type="java.lang.String" initial="xxx"/>
<form-property name="valeursCombo" type="java.lang.String[]" />
<form-property name="valeursListeSimple" type="java.lang.String[]" />
<form-property name="valeursListeMultiple" type="java.lang.String[]"/>
</form-bean>
</form-beans>
<action-mappings>
<action
path="/confirmation"
name="dynaFormulaire"
validate="false"
scope="session"
parameter="/vues/confirmation.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
<forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
</action>
<action
path="/affiche"
parameter="/vues/formulaire.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
<message-resources
parameter="ApplicationResources"
null="false"/>
</struts-config>
يحتوي على ثلاثة أقسام رئيسية:
- إعلان النماذج في قسم <form-beans>
- إعلان الإجراءات في قسم <action-mappings>
- إعلان ملف الموارد في <message-resources>
6.3.4. كائنات نماذج التطبيق (البيانات)
الكائنات المستخدمة لتمثيل نماذج HTML الخاصة بالتطبيق هي من نوع ActionForm أو نوع مشتق (DynaActionForm، DynaValidatorForm، إلخ). وتسمى هذه الكائنات beans لأن بنائها يتبع قواعد JavaBeans. يوجد نموذج bean واحد فقط في تطبيقنا، يسمى dynaFormulaire ومشتق من DynaActionForm. وسيتم استخدامه في الحالات التالية:
- لاحتواء البيانات اللازمة لعرض العرض رقم 1
- لاسترداد القيم من النموذج في العرض رقم 1 عندما يرسله المستخدم
- لاحتواء البيانات اللازمة لعرض العرض رقم 2
ترتبط بنية bean dynaFormulaire ارتباطًا وثيقًا بالنموذج في العرض رقم 1. دعونا نفحصها:
![]() |
رقم | نوع HTML | الدور |
<input name="opt" type="radio" value="yes"> <input name="opt" type="radio" value="no"> | مجموعة من أزرار الاختيار المرتبطة ببعضها (نفس الاسم) | |
<input name="chk1" type="radio" value="on"> <input name="chk2" type="radio" value="on"> <input name="chk3" type="radio" value="on"> | مجموعات من مربعات الاختيار (ليس الاسم نفسه) | |
<input type="text" name="inputField"> | حقل نصي | |
<input type="password" name="password"> | حقل كلمة مرور | |
<textarea name="inputBox">...</textarea> | حقل إدخال متعدد الأسطر | |
<select name="combo" size="1">..</select> | قائمة منسدلة | |
<select name="simpleList" size="3">..</select> | قائمة اختيار واحد | |
<select name="listeMultiple" size="3" multiple>..</select> | قائمة اختيار متعددة | |
<input type="button" value="مسح" onclick='clearList("singleList")'> | زر لإلغاء تحديد العناصر المحددة في simpleList (7) | |
<input type="button" value="مسح" onclick='clearList("multipleList")'> | زر لإلغاء تحديد العناصر المحددة في multipleList (8) | |
<input type="submit" value="إرسال"> | زر إرسال النموذج | |
<input type="hidden" name="secret" value="..."> | حقل مخفي |
لننظر في عدة حالات:
- يُستخدم كائن dynaFormulaire لتخزين القيم من نموذج HTML أعلاه، والتي سيتم إرسالها عبر زر [إرسال]. لذلك يجب أن يحتوي على نفس الحقول الموجودة في نموذج HTML. يتم تحديد نوع الحقل وفقًا للقاعدة التالية:
- إذا كان حقل HTML يوفر قيمة واحدة فقط، فسيكون حقل dynaFormulaire من النوع java.lang.String
- إذا كان حقل HTML يوفر قيمًا متعددة، فسيكون حقل dynaFormulaire من النوع java.lang.String[]
في نموذج HTML أعلاه، يمكن ربط الحقل listeMultiple فقط بقيم متعددة (تلك التي يختارها المستخدم). لذلك، سيكون التعريف الأولي لكائن **dynaFormulaire** كما يلي:
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<form-property name="opt" type="java.lang.String" initial="non"/>
<form-property name="chk1" type="java.lang.String"/>
<form-property name="chk2" type="java.lang.String"/>
<form-property name="chk3" type="java.lang.String"/>
<form-property name="champSaisie" type="java.lang.String" initial=""/>
<form-property name="mdp" type="java.lang.String" initial=""/>
<form-property name="boiteSaisie" type="java.lang.String" initial=""/>
<form-property name="combo" type="java.lang.String"/>
<form-property name="listeSimple" type="java.lang.String"/>
<form-property name="listeMultiple" type="java.lang.String[]"/>
<form-property name="secret" type="java.lang.String" initial="xxx"/>
</form-bean>
كيف سيتم ملء dynaFormulaire بقيم نموذج HTML المرسلة من عميل الويب؟
سيتلقى حقل opt القيمة "yes" إذا تم تحديد حقل HTML <input type="radio" name="opt" value="yes">، والقيمة "no" إذا تم تحديد الحقل <input type="radio" name="opt" value="no">. | |
سيتلقى حقل chk1 القيمة "on" إذا تم تحديد حقل HTML <input name="chk1" type="radio" value="1">؛ وإلا، فلن يتلقى أي شيء. في الحالة الأخيرة، سيحتفظ حقل chk1 بقيمته السابقة. | |
same | |
نفس | |
سيتلقى الحقل `champSaisie` النص الذي أدخله المستخدم في حقل HTML `<input type="text" name="champSaisie">`. قد يكون هذا النص سلسلة فارغة. | |
سيتلقى الحقل mdp النص الذي أدخله المستخدم في حقل HTML <input type="password" name="mdp">. قد يكون هذا النص سلسلة فارغة. | |
سيتلقى حقل inputBox النص الذي أدخله المستخدم في حقل HTML <textarea name="inputBox">...</textarea>. يشكل هذا النص سلسلة واحدة، تتكون من الأسطر التي كتبها المستخدم مفصولة عن بعضها البعض بتسلسل الأحرف "\r\n". قد يكون النص الناتج، اختيارياً، سلسلة فارغة. | |
سيتلقى حقل combo الخيار الذي يختاره المستخدم في حقل HTML <select name="combo" size="1">..</select>. الخيار المحدد هو الذي يظهر في مربع combo. إذا كان خيار HTML المحدد من النوع <option value="XX">YY</option>، فسيتلقى حقل combo القيمة "XX". إذا كان الخيار HTML المحدد من النوع <option>YY</option>، فسيتلقى حقل القائمة المنسدلة القيمة "YY". | |
سيتلقى حقل simpleList الخيار الذي يختاره المستخدم في حقل HTML <select name="simpleList" size="..">..</select> إذا كان هناك خيار. إذا لم يكن هناك خيار، فلن يتلقى حقل simpleList أي قيمة وسيحتفظ بقيمته السابقة. تتبع القيمة المخصصة فعليًا لحقل simpleList القواعد المحددة لمربع القائمة المنسدلة. | |
سيتلقى الحقل listeMultiple من النوع String[] الخيارات التي يختارها المستخدم في حقل HTML <select name="listeMultiple" size=".." multiple>..</select> إن وجدت. وفي حالة عدم وجود أي خيارات، لن يتلقى المصفوف listeMultiple أي قيمة وسيظل محتواه دون تغيير. وتتبع القيم المخصصة فعليًا لمصفوف listeMultiple القواعد المحددة لمربع القائمة المنسدلة. | |
سيتلقى الحقل secret القيمة XX من حقل HTML <input type="hidden" name="secret" value="XX">. قد يكون هذا النص، بشكل اختياري، سلسلة فارغة. |
- يُستخدم كائن dynaFormulaire لتوفير المحتوى الأولي للعرض رقم 1. ستُستخدم قيم الحقول السابقة للأغراض التالية:
يجب أن يكون له القيمة "yes" أو "no" حتى يعرف المتصفح زر الاختيار الذي يجب تحديده | |
إذا كانت قيمة chk1 هي "on"، فسيتم تحديد مربع الاختيار؛ وإلا، فلن يتم تحديده | |
نفس | |
نفس | |
سيتم عرض قيمة الحقل في حقل الإدخال fieldInput | |
سيتم عرض قيمة الحقل في حقل إدخال mdp | |
سيتم عرض قيمة الحقل في مربع الإدخال inputBox | |
تشير قيمة هذا الحقل إلى العنصر الذي يجب تحديده في مربع القائمة المنسدلة عند عرض النموذج | |
same | |
تشير القيم الموجودة في مصفوفة multipleList إلى العناصر التي يجب تحديدها في القائمة المتعددة عند عرض النموذج | |
سيتم تعيين قيمة الحقل إلى سمة value لحقل HTML السري. |
العرض رقم 1 يتطلب معلومات إضافية:
- قائمة القيم المراد عرضها في القائمة المنسدلة
- قائمة القيم المراد عرضها في قائمة `listeSimple`
- قائمة القيم المراد عرضها في قائمة multipleList
هناك عدة طرق لتزويد العرض بهذه المعلومات. على سبيل المثال، يمكن استخدام المصفوفات الموضوعة في الطلب الذي يتم تمريره إلى العرض. هنا، نضع هذه المصفوفات في حبة dynaFormulaire:
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
...
<form-property name="valeursCombo" type="java.lang.String[]" />
<form-property name="valeursListeSimple" type="java.lang.String[]" />
<form-property name="valeursListeMultiple" type="java.lang.String[]"/>
</form-bean>
سيتم تهيئة النموذج dynaFormulaire بواسطة الإجراء /init، الذي سيستدعي كائنًا مشتقًا من Action يسمى InitFormulaireAction. سيكون هذا الكائن مسؤولاً عن إنشاء المصفوفات الثلاث اللازمة لعرض القوائم الثلاث ووضعها في حبة dynaFormulaire. يحدد ملف التكوين نطاق هذه الحبة على session. ونتيجة لذلك، سيضع وحدة التحكم Struts هذه الحبة في الجلسة. وبالتالي، لن نحتاج إلى إعادة إنشائه بين دورات الطلب والاستجابة. وبالتالي، سيتم استدعاء الإجراء /init مرة واحدة فقط.
- يُستخدم كائن dynaFormulaire أيضًا لملء العرض رقم 2. يعرض هذا العرض القيم ببساطة.
6.3.5. إجراءات التطبيق
يتم التعامل مع الإجراءات بواسطة كائنات من نوع Action أو الأنواع المشتقة. يتم تكوين الإجراء داخل علامات <action-mappings>:
<action-mappings>
<action
path="/confirmation"
name="dynaFormulaire"
validate="false"
scope="session"
parameter="/vues/confirmation.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
<forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
</action>
<action
path="/affiche"
parameter="/vues/formulaire.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
لاحظ أنه لا يوجد دائمًا نموذج مرتبط بعمل ما. وهذا هو الحال، أعلاه، مع العمل /affiche. قبل تفصيل كل عمل، دعونا نستعرض كيف يعمل الزوج "العمل-النموذج" داخل علامة <action>:
- تبدأ العملية بطلب من عميل الويب وتنتهي بإرسال صفحة استجابة. وهذه هي دورة الطلب والاستجابة بين العميل والخادم في الويب. يستقبل الطلب وحدة التحكم Struts من نوع ActionServlet أو فئة مشتقة منها. وتقوم وحدة التحكم هذه أيضًا بإرسال الاستجابة.
- يتم إنشاء حبة النموذج من النوع ActionForm أو فئة مشتقة إذا لم تكن موجودة بالفعل. تتحقق وحدة التحكم مما إذا كان بإمكانها العثور على كائن باسم name في النطاق المحدد بواسطة scope. إذا كان الأمر كذلك، فإنها تستخدمه. إذا لم يكن الأمر كذلك، فإنها تنشئه وتضعه في النطاق المحدد بواسطة scope، مرتبطًا بالسمة المحددة بواسطة name.
في مثال الإجراء /init، على سبيل المثال، ستستدعي وحدة التحكم request.getSession().getAttribute("dynaFormulaire") لتحديد ما إذا كان dynaFormulaire قد تم إنشاؤه بالفعل أم لا. إذا لم يكن كذلك، فستقوم بإنشائه وإضافته إلى الجلسة باستخدام عبارة مثل request.getSession().setAttribute("dynaFormulaire", new DynaFormulaire(...)).
- ستبحث وحدة التحكم أيضًا عن كائن Action من النوع المحدد بواسطة السمة type. إذا لم تجده، فستقوم بإنشائه؛ وإلا، فستستخدمه.
- سيتم استدعاء طريقة reset الخاصة بـ form bean. يتم إعادة استخدام هذا bean، باستثناء أثناء إنشائه الأولي. لذلك، فإنه يحتوي على بيانات قد ترغب في "تنظيفها". يتم ذلك في طريقة reset الخاصة بـ ActionForm bean أو فئة مشتقة.
- إذا كان الإجراء هو هدف نموذج تم إرساله، فسيتم نسخ قيم النموذج الموجودة في طلب العميل إلى الحقول التي تحمل نفس الاسم في حبة النموذج. لاحظ أن طريقة إعادة الضبط تم استدعاؤها قبل هذا النسخ.
- إذا حددت التهيئة السمة validate="true"، فسيتم استدعاء طريقة validate الخاصة بـ bean النموذج. يجب أن تقوم هذه الطريقة بعد ذلك بالتحقق من صحة البيانات الموجودة في bean. عادةً ما يحدث هذا التحقق من الصحة فقط عندما يكون النموذج قد تلقى للتو بيانات جديدة عبر نموذج مرسَل وتريد التحقق من صحة تلك البيانات. تُرجع هذه الطريقة أي قائمة بالأخطاء إلى وحدة التحكم في كائن ActionErrors.
- إذا لم يكن كائن ActionErrors فارغًا، يعرض وحدة التحكم العرض المحدد بواسطة سمة الإدخال الخاصة بالإجراء.
- إذا لم يكن التحقق من صحة البيانات مطلوبًا أو إذا كان ناجحًا، يستدعي وحدة التحكم طريقة `execute` الخاصة بكائن `Action` (أو فئة مشتقة) المرتبط بالإجراء الحالي. تتم معالجة طلب عميل الويب ضمن هذه الطريقة. تُرجع طريقة `execute` كائن `ActionForward` مفهرسًا بمفاتيح سلسلة. هذه المفاتيح هي تلك المُعلنة بواسطة علامات `forward` للإجراء المُهيأ. في مثالنا، يحتوي الإجراء `/init` على علامة `forward` واحدة. وهي تربط المفتاح "displayForm" بعرض `form.jsp`.
- يعرض وحدة التحكم العرض المرتبط بالمفتاح المستلم. قد يكون هذا العرض في الواقع إجراءً، وفي هذه الحالة تتكرر العملية السابقة.
الإجراء /init
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
<forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
</action>
- عادةً ما تحدث الإجراء /init مرة واحدة خلال دورة الطلب والاستجابة الأولى عندما يطلب المستخدم عنوان URL http://localhost:8080/formulaire2/init.do
- يتم إنشاء كائن dynaForm أو إعادة استخدامه. يتم استرجاعه (إعادة الاستخدام) أو وضعه (الإنشاء) في الجلسة وفقًا لما تحدده سمة النطاق.
- يتم استدعاء طريقة إعادة تعيينه. ما الذي يجب أن يفعله؟ عادةً، يتم إعادة تعيين حقول كائن ActionForm إلى القيم الافتراضية. ومع ذلك، في هذه الحالة، لن نقوم بذلك، لأن كائن dynaFormulaire يتم وضعه في الجلسة (scope="session"). لذلك يجب أن تحتفظ حقول dynaFormulaire بقيمها. ما هي هذه القيم أثناء الإنشاء الأولي لكائن dynaFormulaire؟ هناك حالتان:
- يحتوي الحقل على قيمة أولية محددة في ملف التكوين:
في هذه الحالة، سيقوم وحدة التحكم Struts بإنشاء هذا الحقل بهذه القيمة الأولية.
- إذا لم يتم تحديد قيمة أولية للحقل في التكوين: تُطبق قواعد التهيئة في Java. بشكل عام، ستكون قيمة الحقول الرقمية صفرًا، وستكون قيمة السلاسل سلسلة فارغة، وستكون قيمة الكائنات الأخرى null.
دعونا نلقي نظرة على التكوين الأولي لـ dynaFormulaire:
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<form-property name="opt" type="java.lang.String" initial="non"/>
<form-property name="chk1" type="java.lang.String"/>
<form-property name="chk2" type="java.lang.String"/>
<form-property name="chk3" type="java.lang.String"/>
<form-property name="champSaisie" type="java.lang.String" initial=""/>
<form-property name="mdp" type="java.lang.String" initial=""/>
<form-property name="boiteSaisie" type="java.lang.String" initial=""/>
<form-property name="combo" type="java.lang.String"/>
<form-property name="listeSimple" type="java.lang.String"/>
<form-property name="listeMultiple" type="java.lang.String[]"/>
<form-property name="secret" type="java.lang.String" initial="xxx"/>
<form-property name="valeursCombo" type="java.lang.String[]" />
<form-property name="valeursListeSimple" type="java.lang.String[]" />
<form-property name="valeursListeMultiple" type="java.lang.String[]"/>
</form-bean>
ستكون القيم الأولية لحقول dynaFormulaire بعد الإنشاء كما يلي:
الحقل | القيمة الأولية |
"لا" | |
سلسلة فارغة | |
سلسلة فارغة | |
سلسلة فارغة | |
سلسلة فارغة | |
سلسلة فارغة | |
سلسلة فارغة | |
مصفوفة من السلاسل الفارغة | |
"xxx" | |
مصفوفة من سلاسل فارغة |
- قد يتصور المرء أن طريقة إعادة التعيين في dynaFormulaire تعين قيمًا للمصفوفات الثلاث التي تملأ القوائم الثلاث في عرض formulaire.jsp. قد يكون هذا ممكنًا هنا لأن البيانات في هذه المصفوفات الثلاث يتم إنشاؤها بشكل عشوائي. ومع ذلك، فإن السيناريو الأكثر شيوعًا هو أن هذه البيانات تأتي من نموذج التطبيق، وهو الحرف M في MVC. هنا، سنتخذ موقفًا وسطًا — للحفاظ على بساطة المثال — من خلال إنشاء هذه القيم بواسطة الإجراء InitFormulaireAction، أي بواسطة الحرف C في MVC.
- ليس هناك حاجة لكتابة طريقة إعادة تعيين في dynaFormulaire، لأن فئة ActionForm التي تنحدر منها تحتوي بالفعل على طريقة لا تفعل شيئًا (لا توجد عمليات تهيئة).
- بمجرد استدعاء طريقة إعادة الضبط في dynaFormulaire، يتحقق وحدة التحكم من سمة التحقق من صحة الإجراء. هنا، تكون القيمة "false". لن يتم استدعاء طريقة التحقق من صحة dynaFormulaire.
- يتم إنشاء كائن InitFormulaireAction أو إعادة استخدامه إذا كان موجودًا بالفعل، ويتم استدعاء طريقة execute الخاصة به. تخصص هذه الطريقة قيمًا عشوائية للمصفوفات الثلاثة في dynaFormulaire: valeursCombo و valeursListeSimple و valeursListeMultiple. تُرجع الطريقة ActionForward بالمفتاح "afficherFormulaire".
- يعرض وحدة التحكم عرض /vues/formulaire.jsp، الذي تم ربطه بالمفتاح "afficherFormulaire" عبر علامة إعادة توجيه من الإجراء /init.
إجراء /confirmation
<action
path="/confirmation"
name="dynaFormulaire"
validate="false"
scope="session"
parameter="/vues/confirmation.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
- يحدث الإجراء /confirmation عندما ينقر المستخدم على زر [Submit] في العرض رقم 1. ثم يقوم المتصفح بـ"إرسال" النموذج الذي ملأه المستخدم إلى وحدة التحكم Struts.
- يتم استرداد كائن dynaFormulaire من الجلسة
- يتم استدعاء طريقة إعادة التعيين الخاصة بها. وبمجرد استدعائها، تقوم وحدة التحكم Struts بنسخ قيم حقول النموذج التي أرسلها العميل إلى الحقول التي تحمل نفس الأسماء في dynaFormulaire. دعونا نستعرض قائمة الحقول في dynaFormulaire ونرى كيف تتم عملية النسخ هذه:
الحقل | كود HTML المرتبط | قيمة الحقل بعد نسخ قيم النموذج |
<input type="radio" name="opt" value="yes">نعم <input type="radio" name="opt" value="no" checked="checked">لا | - "نعم" أو "لا" حسب زر الاختيار المحدد | |
<input type="checkbox" name="chk1" value="on"> | - "on" إذا تم تحديد مربع الاختيار chk1 - يحتفظ بقيمته السابقة إذا لم يتم تحديد مربع الاختيار chk1 | |
<input type="checkbox" name="chk2" value="on"> | - "on" إذا تم تحديد مربع الاختيار chk2 - يحتفظ بقيمته السابقة إذا لم يتم تحديد مربع الاختيار chk2 | |
<input type="checkbox" name="chk2" value="on"> | - "on" إذا تم تحديد مربع الاختيار chk3 - يحتفظ بقيمته السابقة إذا لم يتم تحديد مربع الاختيار chk3 | |
<input type="text" name="inputField" value=""> | - القيمة التي أدخلها المستخدم في inputField | |
<input type="password" name="password" value=""> | - القيمة التي أدخلها المستخدم في حقل كلمة المرور | |
<textarea name="inputBox"></textarea> | - القيمة التي أدخلها المستخدم في textbox | |
<select name="combo">...</select> | - القيمة التي يختارها المستخدم في القائمة المنسدلة | |
<select name="simpleList" size="3">...</select> | - القيمة التي اختارها المستخدم في قائمة بسيطة | |
<select name="listeMultiple" multiple="multiple" size="5"> | - مصفوفة من السلاسل تحتوي على القيم التي اختارها المستخدم في multipleList | |
<input type="hidden" name="secret" value="xxx"> | - "xxx". |
نواجه مشكلة مع الحقول التي لا تتلقى بالضرورة قيمة في الطلب المرسل من المتصفح. ينطبق هذا على مربعات الاختيار chk1 إلى chk3 والقائمتين listeSimple و listeMultiple. في هذه الحالة، تحتفظ هذه الحقول بقيمها السابقة — تلك التي تم الحصول عليها خلال دورة الطلب والاستجابة السابقة.
لنأخذ مربع الاختيار chk1 كمثال، ولنفترض أن المستخدم قد حدد هذا المربع في دورة الطلب والاستجابة السابقة. عندئذ أرسل المتصفح المعلومات chk1="on" في سلسلة معلمات طلبه. وبالتالي، قام مُنشئ الكائن بتعيين القيمة "on" لحقل chk1 في dynaFormulaire. والآن، لنفترض أن المستخدم لم يحدد مربع الاختيار chk1 في الدورة الحالية. في هذه الحالة، في سلسلة معلمات الطلب الجديد، لا يرسل المتصفح شيئًا مثل chk1="off" بل لا يرسل أي شيء. ونتيجة لذلك، سيحتفظ حقل chk1 في dynaFormulaire بقيمته "on" وبالتالي سيكون له قيمة لا تعكس قيمة النموذج الذي تم التحقق من صحته من قبل المستخدم. سنستخدم طريقة إعادة الضبط في dynaFormulaire لحل هذه المشكلة. في هذه الطريقة، سنقوم بتعيين الحقول الثلاثة chk1 و chk2 و chk3 على "off". في مثال chk1 الخاص بنا، إما أن يقوم المستخدم:
- يحدد مربع الاختيار chk1. في هذه الحالة، يرسل المتصفح المعلومات chk1="on" وسيتغير حقل chk1 في dynaFormulaire إلى "on"
- أو لا يحدد مربع الاختيار chk1. عندئذٍ لا يرسل المتصفح قيمة لحقل chk1، والذي سيحتفظ بقيمته السابقة "off". في كلتا الحالتين، تكون القيمة المخزنة في حقل chk1 في dynaFormulaire صحيحة.
المشكلة مشابهة لكل من قوائم simpleList و multiList. إذا لم يتم تحديد أي خيار في هذه القوائم، فلن تكون موجودة في معلمات الطلب وبالتالي ستحتفظ بقيمها السابقة. في طريقة إعادة الضبط في dynaFormulaire، سنقوم بإعادة ضبط simpleList بسلسلة فارغة و multiList بمصفوفة من السلاسل بطول 0.
- بمجرد استدعاء طريقة إعادة تعيين dynaFormulaire، يقوم وحدة التحكم بنسخ المعلومات المرسلة إليها في طلب العميل مرة أخرى إلى حقول dynaFormulaire
- يتم إنشاء كائن ForwardAction أو إعادة استخدامه، ويتم استدعاء طريقة execute الخاصة به. ForwardAction هي فئة محددة مسبقًا تعيد كائن ActionForward يشير إلى العرض المحدد بواسطة سمة "parameter" الخاصة بالإجراء، وفي هذه الحالة /vues/confirmation.jsp.
- يرسل وحدة التحكم هذا العرض. وبذلك يكتمل الدورة.
/display
<action
path="/affiche"
parameter="/vues/formulaire.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
- يتم تشغيل الإجراء /display بالنقر على رابط [العودة إلى النموذج] في العرض رقم 2.
- هنا، لا يوجد نموذج مرتبط بالإجراء. لذلك ننتقل مباشرة إلى تنفيذ طريقة `execute` لكائن `ForwardAction`، والتي ستُرجع كائن `ActionForward` يشير إلى العرض `/vues/formulaire.jsp`.
6.3.6. ملف رسائل التطبيق
القسم الثالث من ملف struts-config.xml هو ملف الرسائل:
يوجد ملف ApplicationResources.properties في WEB-INF/classes. وسيكون فارغًا. على الرغم من أنه فارغ، إلا أنه يجب الإعلان عنه في ملف التكوين؛ وإلا، فإن مكتبة علامات struts-bean، التي سنناقشها لاحقًا، ستولد خطأً. يتم استخدام هذه المكتبة بواسطة عرض confirmation.jsp.
6.4. كود العرض
6.4.1. عرض formulaire.jsp
تذكر أن هذا العرض يظهر في حالتين:
- عند استدعاء الإجراء /init خلال دورة الطلب والاستجابة الأولى
- عند استدعاء الإجراء /affiche خلال الدورات اللاحقة
فيما يلي كود عرض formulaire.jsp:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title>formulaire</title>
</head>
<body background='<html:rewrite page="/images/standard.jpg"/>'>
<h3>Formulaire Struts</h3>
<hr>
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<table border="0">
<tr>
<td>bouton radio</td>
<td>
<html:radio name="dynaFormulaire" property="opt" value="oui">Oui</html:radio>
<html:radio name="dynaFormulaire" property="opt" value="non">Non</html:radio>
</td>
</tr>
<tr>
<td>Cases à cocher</td>
<td>
<html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox>
<html:checkbox name="dynaFormulaire" property="chk2">2</html:checkbox>
<html:checkbox name="dynaFormulaire" property="chk3">3</html:checkbox>
</td>
</tr>
<tr>
<td>Champ de saisie</td>
<td>
<html:text name="dynaFormulaire" property="champSaisie" />
</td>
</tr>
<tr>
<td>Mot de passe</td>
<td>
<html:password name="dynaFormulaire" property="mdp" />
</td>
</tr>
<tr>
<td>Boîte de saisie multilignes</td>
<td>
<html:textarea name="dynaFormulaire" property="boiteSaisie" />
</td>
</tr>
<tr>
<td>Combo</td>
<td>
<html:select name="dynaFormulaire" property="combo">
<html:options name="dynaFormulaire" property="valeursCombo"/>
</html:select>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>Liste à sélection unique</td>
</tr>
<tr>
<td>
<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>
</td>
</tr>
</table>
<td>
<html:select name="dynaFormulaire" property="listeSimple" size="3">
<html:options name="dynaFormulaire" property="valeursListeSimple"/>
</html:select>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>Liste à sélection multiple</td>
</tr>
<tr>
<td>
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>
</td>
</tr>
</table>
</td>
<td>
<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true">
<html:options name="dynaFormulaire" property="valeursListeMultiple"/>
</html:select>
</td>
</tr>
</table>
<html:hidden name="dynaFormulaire" property="secret"/>
<br>
<hr>
<html:submit>Envoyer</html:submit>
</html:form>
</body>
</html>
تستخدم صفحة JSP هذه علامات من مكتبة struts-html. تذكر أنه لاستخدام مكتبة العلامات، يجب عليك:
- تعلنها في ملف web.xml الخاص بالتطبيق باستخدام علامة <tag-lib>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
- ضع كود هذه المكتبة في مكان ما ضمن شجرة دليل التطبيق، هنا WEB-INF/struts-html.tld
- أعلن استخدام هذه المكتبة في بداية صفحات JSP التي تستخدمها:
تستخدم طريقة العرض formulaire.jsp علامات سنشرحها الآن:
<body background="<html:rewrite page="/images/standard.jpg"/>"> | |||
تسمح لك علامة html:rewrite بحذف اسم التطبيق من عناوين URL. ولها سمة واحدة:
لذا، في المثال أعلاه، إذا قررت تسمية التطبيق "form3"، فلن تحتاج إلى إعادة كتابة كود سمة الخلفية. ستقوم علامة `html:rewrite` بإنشاء كود HTML الجديد background="/formulaire3/images/standard.jpg" |
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire"> | |||||||
تقوم علامة html:form بإنشاء علامة النموذج HTML. ولها عدة سمات:
يمكننا أن نلاحظ أنه بشكل افتراضي، يستخدم كود HTML الذي تم إنشاؤه طريقة POST. في كود HTML هذا نفسه، تمت إعادة كتابة عنوان URL الخاص بالإجراء بحيث يبدأ باسم التطبيق وينتهي بـ .do. |
<html:radio name="dynaFormulaire" property="opt" value="yes">نعم</html:radio> | |||||||
تُستخدم علامة html:radio لإنشاء علامة HTML <input type="radio" ...>. وهي تدعم العديد من السمات:
النص الموجود بين علامتي البداية والنهاية هو النص الذي سيتم عرضه بجانب زر الاختيار. |
<html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox> | |||||||
تُستخدم علامة html:checkbox لإنشاء علامة HTML <input type="checkbox" ...>. وهي تدعم العديد من السمات:
النص الموجود بين علامتي البداية والنهاية هو النص الذي سيتم عرضه بجانب مربع الاختيار. |
<html:text name="dynaFormulaire" property="inputField" /> | |||||||
تُستخدم علامة html:text لإنشاء علامة HTML <input type="text" ...>. وهي تدعم العديد من السمات:
|
<html:password name="dynaFormulaire" property="mdp" /> | |
تُستخدم علامة html:password لإنشاء علامة HTML <input type="password" ...>. وهي تدعم العديد من السمات: |
<html:textarea name="dynaFormulaire" property="boiteSaisie" /> | |||||||
تُستخدم علامة HTML:textarea لإنشاء علامة HTML <textarea>...</textarea>. وهي تدعم العديد من السمات:
|
<html:select name="dynaFormulaire" property="combo">....</html:select> | |||||||
تُستخدم علامة HTML:select لإنشاء علامة HTML <select>...</select>. وهي تدعم العديد من السمات:
|
<html:select name="dynaFormulaire" property="combo"> <html:options name="dynaFormulaire" property="comboValues"/> </html:select> | |||||
تُستخدم علامة HTML:options لإنشاء علامات HTML <option>...</option> داخل علامة HTML <select>. هناك طرق مختلفة لتحديد كيفية العثور على القيم لملء عنصر الاختيار. هنا، استخدمنا سمات الاسم والخاصية:
|
يتم إنشاء القائمتين الأخريين بطريقة مشابهة للقائمة السابقة:
<html:select name="dynaFormulaire" property="listeSimple" size="3">
<html:options name="dynaFormulaire" property="valeursListeSimple"/>
</html:select>
في الأعلى، نحدد سمة حجم غير 1 لإنشاء قائمة بدلاً من مربع قائمة منسدلة.
<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true">
<html:options name="dynaFormulaire" property="valeursListeMultiple"/>
</html:select>
في الأعلى، نحدد السمة multiple="true" لإنشاء قائمة ذات اختيارات متعددة.
<html:hidden name="dynaFormulaire" property="secret"/> | |||||
تُستخدم علامة html:hidden لإنشاء علامة HTML <input type="hidden" ...>.
|
لفهم العلاقة بين طريقة العرض «formulaire.jsp» و«dynaFormulaire» التي تمثلها في الذاكرة فهماً تاماً، من المهم أن نتذكر أن «dynaFormulaire» تُستخدم في كل من القراءة والكتابة:
![]() |
يحدث الطلب عندما ينقر المستخدم على زر [إرسال] في النموذج. ثم يقوم المتصفح بـ"إرسال" النموذج HTML إلى الإجراء /confirmation. وقد سبق أن أوضحنا ما يحدث بعد ذلك، وبشكل خاص أن حقول dynaFormulaire ستتلقى قيم الحقول التي تحمل نفس الاسم في النموذج HTML.
ماذا يحدث عندما يطلب وحدة التحكم عرض صفحة formulaire.jsp استجابة لطلب ما؟ دعونا نلقي نظرة فاحصة على العلامات واحدة تلو الأخرى:
<body background="<html:rewrite page="/images/standard.jpg"/>"> | |
تقوم بإنشاء كود HTML |
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire"> ... </html:form> | |
يولد كود HTML |
<html:radio name="dynaFormulaire" property="opt" value="yes">نعم</html:radio> <html:radio name="dynaFormulaire" property="opt" value="no">لا</html:radio> | |
إذا كان حقل opt الخاص بـ dynaFormulaire هو "yes"، فقم بإنشاء كود HTML |
<html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox> <html:checkbox name="dynaFormulaire" property="chk2">2</html:checkbox> <html:checkbox name="dynaForm" property="chk3">3</html:checkbox> | |
إذا كانت حقول chk1 و chk3 في dynaFormulaire "مفعّلة" وحقل chk2 "غير مفعّل"، فقم بإنشاء كود HTML |
<html:text name="dynaFormulaire" property="inputField" /> | |
إذا تم تعيين حقل الإدخال على "هذا اختبار"، فقم بإنشاء كود HTML |
<html:password name="dynaFormulaire" property="password" /> | |
إذا كان حقل كلمة المرور هو "azerty"، فقم بإنشاء كود HTML |
<html:password name="dynaFormulaire" property="mdp" /> | |
إذا كان حقل "mdp" هو "azerty"، فقم بإنشاء كود HTML |
<html:password name="dynaFormulaire" property="mdp" /> | |
إذا كان حقل "mdp" هو "azerty"، فقم بإنشاء كود HTML |
<html:select name="dynaFormulaire" property="combo"> <html:options name="dynaFormulaire" property="comboValues"/> </html:select> | |
إذا كان حقل القائمة المنسدلة هو "combo2"، يقوم بإنشاء كود HTML |
<html:select name="dynaFormulaire" property="simpleList" size="3"> <html:options name="dynaFormulaire" property="simpleListValues"/> </html:select> | |
إذا كان حقل simpleList هو "simple1"، يُنشئ كود HTML |
<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true"> <html:options name="dynaFormulaire" property="multipleListValues"/> </html:select> | |
إذا كان حقل listeMultiple عبارة عن المصفوفة {"multiple0", "multiple2"}، يُنشئ كود HTML |
<html:hidden name="dynaFormulaire" property="secret"/> | |
إذا كان الحقل السري يحتوي على القيمة "xxx"، فقم بإنشاء كود HTML |
<html:submit>إرسال</html:submit> | |
تقوم بإنشاء كود HTML |
آخر ما يجب شرحه هو كود JavaScript المضمن في صفحة JSP والمرتبط بزرّي [Clear] اللذين يلغيان تحديد العناصر المحددة في قائمتي simpleList و multipleList:
<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>
العلامة
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
تولد كود HTML التالي:
لفهم كود JavaScript المرتبط بأزرار [Clear]، دعونا نستعرض كيفية الإشارة إلى العناصر المختلفة لوثيقة الويب داخل كود JavaScript الذي يستخدم تلك الوثيقة:
البيانات | المعنى |
يشير إلى مستند الويب بأكمله | |
يشير إلى مجموعة النماذج المحددة في المستند | |
يشير إلى النموذج رقم i في المستند | |
يشير إلى النموذج <form> الذي تم تعيين سمة الاسم له على "formName" | |
يشير إلى النموذج <form> الذي تساوي سمة الاسم فيه "formName" | |
يشير إلى مجموعة العناصر التي تنتمي إلى النموذج المحدد بواسطة التعبير [form]. تتضمن هذه المجموعة جميع علامات <input> و<textarea> و<select> في النموذج المحدد. | |
يشير إلى العنصر رقم i من [form] | |
يشير إلى العنصر في [form] الذي تساوي سمة الاسم الخاصة به componentName | |
يشير إلى العنصر الموجود في [form] الذي تساوي قيمة سمة name فيه componentName | |
يشير إلى قيمة مكون [component] في النموذج [form] عندما يحتوي كود HTML الخاص به على سمة value (<input>، <textarea>) | |
يشير إلى فهرس الخيار المحدد في قائمة. يمكن استخدامه للقراءة والكتابة. يؤدي تعيين هذه الخاصية إلى -1 إلى إلغاء تحديد جميع العناصر في القائمة. | |
يشير إلى مصفوفة الخيارات المرتبطة بعلامة <select> | |
يشير إلى الخيار رقم i لعلامة <select> المحددة | |
قيمة منطقية تشير إلى ما إذا كان الخيار رقم i للعنصر [select] المحدد محددًا (صحيح) أم لا. يمكن استخدامها للقراءة والكتابة على حد سواء |
دعونا نراجع كود JavaScript الخاص بالزرين:
<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>
عند النقر على الزر، يتم تنفيذ الكود المرتبط بسمة "onclick". هنا، يكون الكود مضمنًا. في أغلب الأحيان، نكتب onclick="function(...)"، حيث function هي دالة محددة داخل علامة <script language="javascript">...</script>. ما الذي يفعله الكود أعلاه؟ دعونا نحلل الكود الخاص بالزر الأول:
يشير إلى مستند الويب الذي يوجد فيه الزر | |
يشير إلى النموذج الذي يوجد فيه الزر | |
يشير إلى مكون simpleList في النموذج | |
يشير إلى مؤشر الخيار المحدد في listeSimple. يؤدي تعيين هذه الخاصية إلى -1 إلى إلغاء تحديد جميع الخيارات. |
6.4.2. عرض confirmation.jsp
تذكر أن هذه العرضة يتم عرضها بعد الإجراء /confirmation، أي بعد أن يتم إرسال النموذج الموجود في عرضة formulaire.jsp بواسطة عميل الويب. والغرض الوحيد منها هو عرض القيم التي أدخلها المستخدم. وفيما يلي شفرتها:
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html>
<head>
<title>Confirmation</title>
</head>
<body background="<html:rewrite page="/images/standard.jpg"/>">
<h3>Confirmation des valeurs saisies</h3>
<hr/>
<table border="1">
<tr>
<td>Bouton radio</td>
<td><bean:write name="dynaFormulaire" scope="session" property="opt"/></td>
</tr>
<tr>
<td>Case à cocher chk1</td>
<td><bean:write name="dynaFormulaire" scope="session" property="chk1"/></td>
</tr>
<tr>
<td>Case à cocher chk2</td>
<td><bean:write name="dynaFormulaire" scope="session" property="chk2"/></td>
</tr>
<tr>
<td>Case à cocher chk3</td>
<td><bean:write name="dynaFormulaire" scope="session" property="chk3"/></td>
</tr>
<tr>
<td>Champ de saisie</td>
<td><bean:write name="dynaFormulaire" scope="session" property="champSaisie"/></td>
</tr>
<tr>
<td>Mot de passe</td>
<td><bean:write name="dynaFormulaire" scope="session" property="mdp"/></td>
</tr>
<tr>
<td>Boîte de saisie</td>
<td><bean:write name="dynaFormulaire" scope="session" property="boiteSaisie"/></td>
</tr>
<tr>
<td>combo</td>
<td><bean:write name="dynaFormulaire" scope="session" property="combo"/></td>
</tr>
<tr>
<td>liste simple</td>
<td><bean:write name="dynaFormulaire" scope="session" property="listeSimple"/></td>
</tr>
<logic:iterate id="choix" indexId="index" name="dynaFormulaire" property="listeMultiple">
<tr>
<td>liste multiple[<bean:write name="index"/>]</td>
<td><bean:write name="choix"/></td>
</tr>
</logic:iterate>
</table>
<br>
<html:link page="/affiche.do">
Retour au formulaire
</html:link>
</body>
</html>
نقدم هنا مكتبتين جديدتين للعلامات: struts-bean و struts-logic. توفر مكتبة struts-bean إمكانية الوصول إلى الكائنات في سياق الطلب أو الجلسة أو التطبيق. تسمح لك مكتبة struts-logic بتنفيذ منطق التنفيذ باستخدام العلامات. ليست أي من هاتين المكتبتين ضرورية بشكل صارم. كما رأينا، يمكن لصفحة JSP:
- استرداد الكائنات من الطلب (request.getAttribute(...))، أو الجلسة (session.getAttribute(...))، أو سياق التطبيق
- تضمين عناصر ديناميكية في كود HTML باستخدام المتغيرات <%= variable %>
- تحتوي على كود Java <% كود Java %>
إن تضمين كود Java في صفحات JSP يزعج أولئك الذين يفضلون الفصل الصارم بين منطق التطبيق (كود Java) والعرض (استخدام العلامات). ولهذا السبب تم إنشاء مكتبات العلامات من أجلهم.
سنتبع نفس النهج الذي اتبعناه في عرض «formulaire.jsp»، وسنشرح كل علامة موجودة في كود «confirmation.jsp» إذا لم نكن قد تناولناها من قبل في عرض «formulaire.jsp». أولاً، لاحظ أن الصفحة تبدأ بإعلان مكتبات العلامات الثلاث التي ستستخدمها:
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
لاحظ أيضًا أنه يجب الإعلان عن هذه المكتبات الثلاث في ملف web.xml الخاص بالتطبيق. سنعلق الآن على العلامات الموجودة في مستند formulaire.jsp:
كتابة قيمة إلى دفق HTML الحالي. تدعم علامة bean:write السمات التالية: name: اسم الكائن المراد استخدامه scope: النطاق (request، session، context) الذي سيتم البحث فيه عن هذا الكائن property: حقل الكائن المحدد بالاسم الذي سيتم كتابة خاصيته. يمكن أن يكون هذا الحقل كائنًا من أي نوع. سيتم استخدام طريقة toString الخاصة بالكائن. هنا، يتم كتابة قيمة حقل opt في dynaFormulaire. ستكون النتيجة إما "yes" إذا قام المستخدم بتحديد زر الاختيار الذي يحتوي على السمة value="yes"، أو "no" إذا قام بتحديد زر الاختيار الذي يحتوي على السمة value="no" |
تقوم بكتابة قيمة حقل chk1 في dynaFormulaire. وستكون النتيجة إما "on" إذا قام المستخدم بتحديد المربع، أو "off" في حالة عدم تحديده. وينطبق الأمر نفسه على chk2 و chk3. |
تقوم بكتابة قيمة حقل champSaisie في dynaFormulaire، أي النص الذي يكتبه المستخدم في هذا الحقل. وينطبق الأمر نفسه على mdp و boiteSaisie. |
تقوم بكتابة قيمة حقل القائمة المنسدلة في dynaFormulaire. وستكون هذه هي سمة القيمة لعنصر <option> الذي اختاره المستخدم. |
تقوم بكتابة قيمة حقل simpleList في dynaForm. وستحتوي على سمة value لعنصر <option> الذي اختاره المستخدم، في حال تم اختيار عنصر ما. وإلا، فستكون سلسلة فارغة. |
هنا، نقدم علامات المنطق. نحن نتعامل مع قائمة متعددة الخيارات. قيمة حقل listeMultiple الخاص بكائن dynaFormulaire هي مصفوفة من سلاسل الأحرف. في Java، كنا سنكتب حلقة. تسمح لنا علامة logic:iterate بتنفيذ هذه الحلقة نفسها دون كتابة كود Java. في هذا المثال، تحتوي علامة logic:iterate على السمات التالية: name="dynaFormulaire": اسم الكائن المراد استخدامه property="listeMultiple": اسم الخاصية في الكائن المحدد بالاسم الذي يحتوي على المجموعة المراد تكرارها في الحلقة. هنا، هذه المجموعة هي مصفوفة القيم المحددة في listeMultiple. قد تكون هذه المصفوفة فارغة. id="choix": معرف يشير إلى العنصر الحالي للمصفوفة في كل تكرار. خلال التكرار الأول، سيمثل choix listeMultiple[0]، وخلال التكرار الثاني سيمثل listeMultiple[1]، وهكذا دواليك. indexID="index": معرف يشير إلى فهرس عنصر المصفوفة الحالي في كل تكرار للحلقة. خلال التكرار الأول، سيكون لـ index القيمة 0؛ وخلال التكرار الثاني، القيمة 1؛ وهكذا دواليك. يتم تكرار كود HTML الموجود بين العلامتين <logic:iterate ...> و</logic:iterate> لكل عنصر في المجموعة المحددة بواسطة الزوج (name,property). الجزء الديناميكي من هذا الكود هو كما يلي:
بناءً على ما قيل سابقًا، في التكرار رقم i (i>=0)، يكون كود HTML الذي تم إنشاؤه مكافئًا لما يلي: |
رابطًا نسبيًا لسياق التطبيق، مما يلغي الحاجة إلى معرفة السياق. رمز HTML الذي تولده هذه العلامة هو كما يلي: |
6.5. فئات Java
يشير ملف التكوين struts-config.xml إلى فئتين من فئات Java:
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
...
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
فئة DynaFormulaire هي الفئة التي ستحتوي على القيم من العرض رقم 1، formulaire.jsp. فئة InitFormulaireAction هي الفئة التي ستعالج قيم النموذج المرسلة عبر زر [Submit] في formulaire.jsp.
6.5.1. فئة DynaFormulaire
للاحتفاظ بقيم النموذج، يكفي وجود كائن من نوع DynaActionForm ما لم تكن بحاجة إلى تجاوز إحدى طرق إعادة الضبط أو التحقق من صحة هذه الفئة. هنا، لا يلزم تجاوز طريقة validate نظرًا لعدم إجراء أي تحقق من صحة البيانات. ومع ذلك، يلزم تجاوز طريقة reset. ويرجع ذلك إلى أن حقول كائن DynaFormulaire ستتلقى قيمها من النموذج المرسَل بواسطة عميل الويب. ومع ذلك، قد لا تتلقى بعض الحقول قيمة إذا لم تكن موجودة في الطلب. ويحدث هذا في الحالات التالية:
- مربع اختيار لم يتم تحديده من قبل المستخدم
- قائمة تحتوي على أكثر من خيار واحد ولم يتم تحديد أي منها
بالنسبة للنماذج التي تحتوي على هذا النوع من المكونات، يجب أن
- تعيين القيمة "off" للحقل المرتبط بمربع الاختيار
- تعيين السلسلة الفارغة للحقل المرتبط بقائمة الاختيار الفردي
- تعيين مصفوفة فارغة من السلاسل إلى الحقل المرتبط بقائمة الاختيار المتعدد
وبالتالي، إذا لم تتلقى هذه الحقول قيمة من الاستعلام، فإنها تحتفظ بالقيمة التي تم تعيينها بواسطة إعادة الضبط، والتي تتوافق مع حالة المكون في النموذج الذي تم التحقق من صحته من قبل المستخدم (مربع الاختيار غير محدد، قائمة بدون عناصر محددة).
فيما يلي كود فئة DynaFormulaire، وهي فئة فرعية من DynaActionForm:
package istia.st.struts.formulaire;
import org.apache.struts.action.DynaActionForm;
import org.apache.struts.action.ActionMapping;
import javax.servlet.http.HttpServletRequest;
public class DynaFormulaire extends DynaActionForm {
public void reset(ActionMapping mapping, HttpServletRequest request){
// reset checkboxes - value off
set("chk1","off");
set("chk2","off");
set("chk2","off");
// reset listeSimple - empty string
set("listeSimple","");
// reset listeMultiple - empty table
set("listeMultiple",new String[]{});
}
}
6.5.2. فئة InitFormAction
ترتبط فئة InitFormAction بالإجراء /init في ملف struts-config.xml:
<action
path="/init"
name="dynaFormulaire"
validate="false"
scope="session"
type="istia.st.struts.formulaire.InitFormulaireAction"
>
<forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
</action>
يتم استخدام الإجراء /init مرة واحدة فقط أثناء الإنشاء الأولي لكائن DynaForm. والغرض منه هو توفير محتوى لقوائم الاختيار الثلاث الخاصة بالنموذج: simpleList و multipleList و dropdownList. ويتم توفير هذا المحتوى في شكل ثلاثة مصفوفات، وهي خصائص لكائن dynaForm:
<form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
<form-property name="opt" type="java.lang.String" initial="non"/>
...
<form-property name="valeursCombo" type="java.lang.String[]" />
<form-property name="valeursListeSimple" type="java.lang.String[]" />
<form-property name="valeursListeMultiple" type="java.lang.String[]"/>
</form-bean>
بمجرد تهيئة المصفوفات valuesCombo و valuesSingleList و valuesMultipleList بواسطة InitFormAction، لن تكون هناك حاجة إلى تهيئتها مرة أخرى. ويرجع ذلك إلى أن كائن dynaForm يتم وضعه في الجلسة، وبالتالي يحتفظ بقيمته عبر دورات الطلب والاستجابة. ولهذا السبب يتم تنفيذ الإجراء /init مرة واحدة فقط. وفيما يلي كود InitFormAction:
package istia.st.struts.formulaire;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class InitFormulaireAction
extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// prepares the form to be displayed
// we put the information needed for the form in its bean
DynaFormulaire formulaire = (DynaFormulaire) form;
formulaire.set("valeursCombo", getValeurs(5, "combo"));
formulaire.set("valeursListeSimple", getValeurs(7, "simple"));
formulaire.set("valeursListeMultiple", getValeurs(10, "multiple"));
// we give back
return mapping.findForward("afficherFormulaire");
} //execute
// list of combo values
private String[] getValeurs(int taille, String label) {
String[] valeurs = new String[taille];
for (int i = 0; i < taille; i++) {
valeurs[i] = label + i;
}
return valeurs;
}
}
- تُوسّع هذه الفئة فئة Action. وهذا أمر إلزامي.
- يستخدم وحدة التحكم Struts كائن Action عبر طريقة execute الخاصة به. ولذلك، فإن هذه هي الطريقة التي يجب إعادة تعريفها. تتلقى هذه الطريقة المعلمات التالية:
- ActionMapping mapping: كائن يمثل تكوين التطبيق في struts-config.xml
- ActionForm form: النموذج المرتبط بالإجراء، إذا تم تعريفه في تكوين الإجراء (سمة اسم الإجراء).
- HttpServletRequest request: طلب العميل
- HttpServletResponse: الاستجابة للعميل
- يجب أن تقوم فئة InitFormulaireAction بتهيئة النموذج dynaFormulaire. يتم تمرير هذا إلى طريقة execute كمعلمة النموذج ActionForm. تذكر أن dynaFormulaire من النوع DynaFormulaire، وهي فئة مشتقة من فئة DynaActionForm، والتي هي نفسها مشتقة من فئة ActionForm.
- في طريقة execute، يتم تعيين القيم إلى الحقول الثلاثة valeursCombo و valeursListeSimple و valeursListeMultiple باستخدام طريقة set لفئة DynaActionForm. هذه القيم هي مصفوفات عشوائية من أجل التبسيط. لاحظ أن طريقة set تعين قيمة لحقل موجود. ولا يمكن استخدامها لإنشاء حقول جديدة. ولهذا السبب من الضروري تعريف الحقول الثلاثة valeursCombo و valeursListeSimple و valeursListeMultiple في تعريف كائن dynaFormulaire في struts-config.xml.
- تنتهي طريقة execute بإرجاع مفتاح العرض المراد عرضه إلى وحدة التحكم كاستجابة للعميل. هنا، هو مفتاح afficherFormulaire، الذي تم ربطه في ملف struts-config.xml بعرض /vues/formulaire.jsp.
6.6. النشر
هيكل دليل التطبيق كما يلي:
![]() | ![]() |
![]() | ![]() |


يرجى ملاحظة أن ملف ApplicationResources.properties المذكور أعلاه مطلوب من قِبل مكتبة العلامات struts-bean. ونحن نعلم أن هذا الملف يحتوي على رسائل التطبيق. ويمكن لمكتبة struts-bean الوصول إلى هذه الرسائل. وفي هذه الحالة، لا يحدد تطبيقنا أي رسائل. ولذلك، فإن ملف ApplicationResources.properties موجود ولكنه فارغ.
6.7. الخلاصة
في هذا الدرس، قمنا بتفصيل كيفية إدارة المكونات المختلفة لنموذج HTML. يمكننا الآن استخدام نماذج معقدة في تطبيقات Struts الخاصة بنا.






