Skip to content

13. المثال 10 – تحويل الأعداد الحقيقية والتحقق من صحتها

يتيح التطبيق الجديد إدخال الأعداد الحقيقية:

  • إلى [1]، ونموذج الإدخال
  • إلى [2]، والنتيجة المُرجعة

يعمل التطبيق بطريقة مشابهة لتلك المستخدمة في إدخال الأعداد الصحيحة، لذا سنكتفي بتوضيح النقاط التي تختلف فقط.

13.1. مشروع NetBeans

مشروع Netbeans هو كما يلي:

  • في [1]، طرق عرض التطبيق
  • [Accueil.jsp]: الصفحة الرئيسية
  • [FormDouble.jsp]: نموذج الإدخال
  • [ConfirmationDouble.jsp]: صفحة التأكيد
  • إلى [2]، وملف الرسائل [messages.properties] وملف التكوين الرئيسي لـ Struts
  • في [3]:
  • [FormDouble.java]: الإجراء الذي يعرض النموذج ويعالجه
  • [FormDouble-validation.xml]: قواعد التحقق من صحة الإجراء [FormDouble]. يقوم هذا الملف بتفويض عمليات التحقق هذه إلى النموذج وفقًا للطريقة التي تم استعراضها للتو.
  • [FormDoubleModel]: نموذج الإجراء [FormDouble]
  • [FormDoubleModel-validation.xml]: قواعد التحقق من صحة النموذج
  • [FormDoubleModel.properties]: ملف رسائل النموذج
  • [example.xml]: ملف التكوين الثانوي لـ Struts

13.2. تكوين المشروع

يتم تكوين المشروع بشكل أساسي من خلال الملف التالي [example.xml]:


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
  <package name="example" namespace="/example" extends="struts-default">
    <action name="Accueil">
      <result name="success">/example/Accueil.jsp</result>
    </action>
    <action name="FormDouble" class="example.FormDouble">
      <result name="input">/example/FormDouble.jsp</result>
      <result name="cancel" type="redirect">/example/Accueil.jsp</result>
      <result name="success">/example/ConfirmationFormDouble.jsp</result>
    </action>
  </package>
</struts>

وهو مشابه للملف الذي تمت دراسته لإدخال الأعداد الصحيحة.

13.3. ملفات الرسائل

ملف [messages.properties] هو كما يلي:


Accueil.titre=Accueil
Accueil.message=Struts 2 - Conversions et validations
Accueil.FormDouble=Saisie de nombres r\u00e9els
Form.titre=Conversions et validations
FormDouble.message=Struts 2 - Conversion et validation de nombres r\u00e9els
FormDouble.conseil=Tapez les nombres r\u00e9els avec une virgule comme 10,7
Form.submitText=Valider
Form.cancelText=Annuler
Form.clearModel=Raz mod\u00e8le
Confirmation.titre=Confirmation
Confirmation.message=Confirmation des valeurs saisies
Confirmation.champ=champ
Confirmation.valeur=valeur
Confirmation.lien=Formulaire de test
xwork.default.invalid.fieldvalue=Valeur invalide pour le champ "{0}".

الملف [FormDoubleModel.properties] هو التالي:


double.format={0,number}
double1.prompt=1-Nombre r\u00E9el
double1.error=Tapez un nombre r\u00E9el
double2.prompt=2-Nombre r\u00E9el
double2.error=Tapez un nombre r\u00E9el
double3.prompt=3-Nombre r\u00E9el >=2.64
double3.error=Tapez un nombre r\u00E9el >=2.64
double4.prompt=4-Nombre r\u00E9el <8.32
double4.error=Tapez un nombre r\u00E9el <8.32
double5.prompt=5-Nombre r\u00E9el dans l''intervalle [2.64,8.32[
double5.error=Tapez un nombre r\u00E9el dans l''intervalle [2.64,8.32[
double6.prompt=6-Nombre r\u00E9el dans l''intervalle [2.64,8.32]
double6.error=Tapez un nombre r\u00E9el dans l''intervalle [2.64,8.32]

السطر 1 يلعب دورًا مهمًا. سنعود إلى هذا لاحقًا.

13.4. نموذج الإدخال

تبدو طريقة العرض [FormDouble.jsp] كما يلي:


<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
  <head>
    <title><s:text name="Form.titre"/></title>
    <s:head/>
  </head>

  <body background="<s:url value="/ressources/standard.jpg"/>">
    <h2><s:text name="FormDouble.message"/></h2>
    <h4><s:text name="FormDouble.conseil"/></h4>
    <s:form name="formulaire" action="FormDouble">
      <s:textfield name="double1" key="double1.prompt"/>
      <s:textfield name="double2" key="double2.prompt" value="%{#parameters['double2']!=null ? #parameters['double2'] : double2==null ? '' :getText('double.format',{double2})}"/>
      <s:textfield name="double3" key="double3.prompt" value="%{#parameters['double3']!=null ? #parameters['double3'] : double3==null ? '' :getText('double.format',{double3})}"/>
      <s:textfield name="double4" key="double4.prompt" value="%{#parameters['double4']!=null ? #parameters['double4'] : double4==null ? '' :getText('double.format',{double4})}"/>
      <s:textfield name="double5" key="double5.prompt" value="%{#parameters['double5']!=null ? #parameters['double5'] : double5==null ? '' :getText('double.format',{double5})}"/>
      <s:textfield name="double6" key="double6.prompt"/>
      <s:submit key="Form.submitText" method="execute"/>
    </s:form>
    <br/>
    <s:url id="url" action="FormDouble" method="cancel"/>
    <s:a href="%{url}"><s:text name="Form.cancelText"/></s:a>
    <br/>
    <s:url id="url" action="FormDouble" method="clearModel"/>
    <s:a href="%{url}"><s:text name="Form.clearModel"/></s:a>
  </body>
</html>

السطور من 13 إلى 18 هي الحقول الستة المخصصة لإدخال الأرقام الحقيقية. الحقول من double2 إلى double5 لها سمة معقدة هي value. عادةً، ينبغي أن تكون حقول الإدخال الستة كما يلي:


      <s:textfield name="double1" key="double1.prompt"/>
      <s:textfield name="double2" key="double2.prompt"/>
      <s:textfield name="double3" key="double3.prompt"/>
      <s:textfield name="double4" key="double4.prompt"/>
      <s:textfield name="double5" key="double5.prompt"/>
<s:textfield name="double6" key="double6.prompt"/>

ولحل بعض المشكلات التي واجهناها أثناء الاختبارات، كان لا بد من زيادة تعقيد الأمور. في الوقت الحالي، يمكن للقارئ تجاهل هذا التعقيد. سنشرحه لاحقًا.

13.5. شاشة التأكيد

تبدو شاشة التأكيد [ConfirmationFormDouble.jsp] كما يلي:

Image

ورمزها هو كما يلي:


<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
  <head>
    <title><s:text name="Confirmation.titre"/></title>
    <s:head/>
  </head>

  <body background="<s:url value="/ressources/standard.jpg"/>">
    <h2><s:text name="Confirmation.message"/></h2>
    <table border="1">
      <tr>
        <th><s:text name="Confirmation.champ"/></th>
        <th><s:text name="Confirmation.valeur"/></th>
      </tr>
      <tr>
        <td><s:text name="double1.prompt"/></td>
        <td><s:text name="double1"/></td>
      </tr>
      <tr>
        <td><s:text name="double2.prompt"/></td>
        <td>
          <s:text name="double.format">
            <s:param value="double2"/>
          </s:text>
        </td>
      </tr>
      <tr>
        <td><s:text name="double3.prompt"/></td>
        <td>
          <s:text name="double.format">
            <s:param value="double3"/>
          </s:text>
        </td>
      </tr>
      <tr>
        <td><s:text name="double4.prompt"/></td>
        <td>
          <s:text name="double.format">
            <s:param value="double4"/>
          </s:text>
        </td>
      </tr>
      <tr>
        <td><s:text name="double5.prompt"/></td>
        <td>
          <s:text name="double.format">
            <s:param value="double5"/>
          </s:text>
        </td>
      </tr>
      <tr>
        <td><s:text name="double6.prompt"/></td>
        <td><s:text name="double6"/></td>
      </tr>
    </table>
    <br/>
    <s:url id="url" action="FormDouble!input"/>
    <s:a href="%{url}"><s:text name="Confirmation.lien"/></s:a>
  </body>
</html>

تكتفي طريقة العرض [ConfirmationFormDouble.jsp] بعرض النموذج [FormDoubleModel]. توضح الأسطر 47-49 عرض رقم حقيقي. نريد أن يأخذ هذا العرض في الاعتبار localisation الخاص بالتطبيق. ووفقًا لذلك، لن يتم عرض الرقم الحقيقي بنفس الطريقة في فرنسا (10,7) وفي بريطانيا العظمى (10.7). ولهذا الغرض، نستخدم العلامة <s:text> التي كنا نستخدمها حتى الآن لتدويل التطبيق. وبالتالي، تُستخدم هذه العلامة أيضًا في عملية الترجمة.

وهنا، مفتاح الرسالة المستخدم هو double.format. ويوجد هذا المفتاح في الملف [FormDoubleModel.properties]:


double.format={0,number}

القيمة المرتبطة بالمفتاح هنا ليست رسالة، بل تنسيق عرض:

  • 0 هو معلمة تمثل القيمة المراد عرضها. وفي هذه الحالة، سيكون الحقل double5 في النموذج.
  • يمثل «number» التنسيق الرقمي. وسيتم تكييفه مع كل بلد. وبدون هذا التنسيق، سيظل الرقم 10.7 معروضًا على أنه 10.7 بغض النظر عن البلد.

العلامة


         <s:text name="double.format">
            <s:param value="double5"/>
</s:text>

يعرض الرسالة {0, number} حيث سيحل المعلمة double5 (السطر 2) محل المعلمة 0 في التنسيق. وبالتالي، سيتم عرض النموذج double5 بالتنسيق الرقمي المخصص للبلد.

13.6. القالب [FormDoubleModel]

يتم إدراج الحقول من double1 إلى double6 من النموذج [FormDouble.jsp] في النموذج [FormDoubleModel] التالي:


package example;

public class FormDoubleModel {

  // منشئ بدون معلمات
  public FormDoubleModel() {
  }
  // الحقول
  private String double1;
  private Double double2;
  private Double double3;
  private Double double4;
  private Double double5;
  private String double6;

  // إعادة تعيين النموذج
  public void clearModel() {
    double1 = null;
    double2 = null;
    double3 = null;
    double4 = null;
    double5 = null;
    double6 = null;
  }

  // أدوات الاسترجاع والتعيين
   ...
}
  • الحقول double1 و double6 من النوع String
  • الحقول الأخرى من النوع Double

13.7. التحقق من صحة النموذج

يتم التحكم في التحقق من صحة النموذج بواسطة ملفين: [FormDouble-validation.xml] و [FormDoubleModel-validation.xml].

يقوم الملف [FormDouble-validation.xml] بتفويض عمليات التحقق إلى الملف [FormDoubleModel-validation.xml]:


<!--
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//
EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-->
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//
EN" "http://localhost:8084/exemple-10/example/xwork-validator-1.0.2.dtd">

<validators>
  <field name="model" >
    <field-validator type="visitor">
      <param name="appendPrefix">false</param>
      <message/>
    </field-validator>
  </field>
</validators>

لقد صادفنا هذا الملف من قبل.

يحتوي الملف [FormDoubleModel-validation.xml] على قواعد التحقق من الصحة التالية:


<!--
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//
EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-->

<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//
EN" "http://localhost:8084/exemple-10/example/xwork-validator-1.0.2.dtd">


<validators>

  <field name="double1" >
    <field-validator type="requiredstring" short-circuit="true">
      <message key="double1.error"/>
    </field-validator>
    <field-validator type="regex" short-circuit="true">
      <param name="expression">^[+|-]*\s*\d+(,\d+)*$</param>
      <param name="trim">true</param>
      <message key="double1.error"/>
    </field-validator>
  </field>

  <field name="double2" >
    <field-validator type="required" short-circuit="true">
      <message key="double2.error"/>
    </field-validator>
    <field-validator type="conversion" short-circuit="true">
      <message key="double2.error"/>
    </field-validator>
  </field>

  <field name="double3" >
    <field-validator type="required" short-circuit="true">
      <message key="double3.error"/>
    </field-validator>
    <field-validator type="conversion" short-circuit="true">
      <message key="double3.error"/>
    </field-validator>
    <field-validator type="double" short-circuit="true">
      <param name="minInclusive">2.64</param>
      <message key="double3.error"/>
    </field-validator>
  </field>

  <field name="double4" >
    <field-validator type="required" short-circuit="true">
      <message key="double4.error"/>
    </field-validator>
    <field-validator type="conversion" short-circuit="true">
      <message key="double4.error"/>
    </field-validator>
    <field-validator type="double" short-circuit="true">
      <param name="maxExclusive">8.32</param>
      <message key="double4.error"/>
    </field-validator>
  </field>

  <field name="double5" >
    <field-validator type="required" short-circuit="true">
      <message key="double5.error"/>
    </field-validator>
    <field-validator type="conversion" short-circuit="true">
      <message key="double5.error"/>
    </field-validator>
    <field-validator type="double" short-circuit="true">
      <param name="minInclusive">2.64</param>
      <param name="maxExclusive">8.32</param>
      <message key="double5.error"/>
    </field-validator>
  </field>

  <field name="double6" >
    <field-validator type="requiredstring" short-circuit="true">
      <message key="double6.error"/>
    </field-validator>
    <field-validator type="regex" short-circuit="true">
      <param name="expression">^[+|-]*\s*\d+(,\d+)*$</param>
      <param name="trim">true</param>
      <message key="double6.error"/>
    </field-validator>
  </field>
</validators>
  • تتحقق القاعدة الواردة في الأسطر 12-21 من أن حقل الإدخال double1 يتبع نموذج تعبير منتظم يمثل عددًا حقيقيًا.
  • تتحقق القاعدة الواردة في الأسطر 23-30 من أن حقل الإدخال double2 يمكن تحويله إلى عدد حقيقي مزدوج.
  • تتحقق القاعدة الواردة في الأسطر 32-43 من أن حقل الإدخال double3 يمكن تحويله إلى عدد حقيقي مزدوج >=2.64. وتجدر الإشارة إلى أنه يجب استخدام الترميز الأنجلوساكسوني للأعداد الحقيقية.
  • تتحقق القاعدة الواردة في الأسطر 45-56 من إمكانية تحويل حقل الإدخال double4 إلى عدد حقيقي من النوع «double» <8.32.
  • تتحقق القاعدة الواردة في الأسطر 58-70 من أن حقل الإدخال double5 يمكن تحويله إلى عدد حقيقي من النوع «double» يقع في الفترة [2.64,8.32[.
  • تتحقق القاعدة الواردة في الأسطر 72-80 من أن الحقل double6 يتوافق مع نموذج تعبير منتظم يمثل عددًا حقيقيًّا.

بمجرد معالجة الملف [FormDoubleModel-validation.xml] بواسطة أداة اعتراض التحقق من الصحة، تقوم هذه الأداة بتنفيذ الطريقة validate الخاصة بالإجراء [FormDouble] في حال وجودها. وسنقدمها بالتزامن مع عرض الإجراء بأكمله.

13.8. الإجراء [FormDouble]

الإجراء [FormDouble] هو كما يلي:


package example;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.interceptor.validation.SkipValidation;

public class FormDouble extends ActionSupport implements ModelDriven, SessionAware {

  // منشئ بدون معلمات
  public FormDouble() {
  }

  // نموذج الإجراء
  public Object getModel() {
    if (session.get("model") == null) {
      session.put("model", new FormDoubleModel());
    }
    return session.get("model");
  }

  @SkipValidation
  public String clearModel() {
    // إعادة تعيين النموذج
    ((FormDoubleModel) getModel()).clearModel();
    // النتيجة
    return INPUT;
  }

  public String cancel() {
    // تنظيف النموذج
    ((FormDoubleModel) getModel()).clearModel();
    // النتيجة
    return "cancel";
  }
  // SessionAware
  Map<String, Object> session;

  public void setSession(Map<String, Object> session) {
    this.session = session;
  }

  // التحقق من الصحة
  @Override
  public void validate() {
    // هل الإدخال المكرر 6 صحيح؟
    if (getFieldErrors().get("double6") == null) {
      // يتم استبدال الفاصلة بالنقطة في السلسلة double6
      String strDouble6 = (((FormDoubleModel) getModel()).getDouble6()).replace(',', '.');
      // سلسلة --> double
      double double6 = Double.parseDouble(strDouble6);
      // التحقق
      if (double6 < 2.64 || double6 > 8.32) {
        addFieldError("double6", getText("double6.error"));
      }
    }
  }
}

تم إنشاء الإجراء [FormDouble] على نفس نموذج الإجراء [FormInt]. لن نعلق إلا على الأسلوب validate. نذكر أن الأسلوب validate يتم تنفيذه بعد معالجة ملف التحقق [FormDoubleModel-validation.xml] وقبل تنفيذ الأسلوب execute.

  • السطر 48: إذا كانت هناك أخطاء موجودة بالفعل في الحقل double6، فلا يتم اتخاذ أي إجراء إضافي.
  • السطر 50: حصلنا على سلسلة نصية بالصيغة 45,67. تم تخزينها في الحقل double6 في النموذج. يتم استبدال الفاصلة بالنقطة للحصول على 45.67.
  • السطر 52: يتم تحويل السلسلة 45.67 إلى عدد حقيقي مزدوج. ومن المفترض أن ينجح ذلك لأن السلسلة double6 تتوافق مع تنسيق العدد الحقيقي.
  • السطر 54: يتم التحقق من أن العدد الحقيقي المزدوج الناتج يقع ضمن النطاق [2.64, 8.32].
  • السطر 55: إذا لم يكن الأمر كذلك، تُرفق رسالة خطأ المفتاح double6.error بالحقل double6. وستُوجد هذه الرسالة في الملف [FormDoubleModel.properties]. وسيتم عرضها عند إعادة عرض النموذج الذي يحتوي على الأخطاء.

13.9. التفاصيل الأخيرة

الآن، لنعد إلى تعقيد حقول الإدخال في النموذج [FormDouble.jsp]. سنناقش الحقل double2. ويمتد هذا التحليل ليشمل الحقول من double3 إلى double5 التي تتبع نموذجًا من النوع Double. أما بالنسبة للحقول double1 و double6 التي لها نموذج من النوع String، فلا توجد أي مشكلة.

حقل الإدخال double2 هو كما يلي:


<s:textfield name="double2" key="double2.prompt" value="%{#parameters['double2']!=null ? #parameters['double2'] : double2==null ? '' :getText('double.format',{double2})}"/>

لنبدأ بالعلامة الأبسط:


<s:textfield name="double2" key="double2.prompt"/>

ولنرى ما يحدث:

  • في [1]، يتم التحقق من صحة الرقم double2. في لقطة الشاشة، لا يظهر ذلك بوضوح، لكننا أدخلنا الرقم بفاصلة.
  • في [2]، نرى شاشة التأكيد. وقد اجتازت القيمة المدخلة double2 اختبارات التحقق من الصحة. ويتم عرض الرقم بفاصلة.
  • في [3]، نعود إلى النموذج
  • في [4]، النموذج. ما لا تظهره لقطة الشاشة بشكل واضح هو أن الرقم double2 الذي كان في البداية 4,32 أصبح 4.32 مع نقطة عشرية.
  • في [5]، نعيد التحقق من صحة النموذج دون تغيير أي شيء
  • في [6]، يتم الإبلاغ عن خطأ في الحقل double2.

المشكلة هي التالية:

  • في البداية، في [1]، تم تحويل سلسلة الإدخال "4,32" بنجاح إلى عدد حقيقي 4.32. وهذا يعني أن عملية التحويل من String إلى Double قد نجحت، وبالتالي فإن Struts يأخذ في الاعتبار الإعدادات المحلية، وهي في هذه الحالة فرنسا.
  • يعرض النموذج الجديد [4] في الحقل double2 القيمة الحقيقية 4.32. ونظرًا لعدم ترجمة طريقة العرض، فإنه يعرضها افتراضيًّا بالصيغة الأنجلوساكسونية، c.a.d، مع نقطة عشرية. لذا، عند التحويل من نوع «Double» إلى «String»، لا يأخذ Struts الإعدادات المحلية في الاعتبار، وإلا لكان قد عرض 4,32 مع فاصلة.

وهذا أمر غير متسق على أقل تقدير. لكن لا بأس، سنقوم بتعريب عرض الرقم 4.32. تصبح علامة الإدخال كما يلي:


<s:textfield name="double2" key="double2.prompt" value="%{getText('double.format',{double2})}"/>

يحدد السمة value القيمة المراد عرضها في الحقل double2. وهذه القيمة هي قيمة تعبير OGNL. لنتذكر تعريف المفتاح double.format في الملف [FormDoubleModel.properties]:


double.format={0,number}

تسمح الطريقة getText('المفتاح') بالحصول على الرسالة المرتبطة بمفتاح ما. ويتم البحث عن هذا المفتاح في الملف المطابق للإعدادات المحلية الحالية. وبالتالي، إذا كانت الإعدادات المحلية هي «es» (إسبانيا)، فسيتم البحث عن المفتاح double.format في الملف [FormDoubleModel_es.properties].

تسمح الطريقة getText('المفتاح', {param0, param1, ...}) بالعثور على رسالة معينة المعلمات. الرسالة

{0, number}

هي رسالة تم تعيين معلماتها بواسطة المعلمة 0. وهذه المعلمة هي معلمة موضعية. ستقوم الطريقة getText('double.format', {double2}) بتعيين الرقم double2 للمعلمة 0. وفي النهاية، يتم طلب قيمة double2 بالصيغة الرقمية المترجمة. في فرنسا، سيتم ترجمة الرقم 4.56 إلى السلسلة "4,56".

بعد هذا التحويل، نعيد إجراء الاختبارات.

فور العرض الأولي للنموذج، تظهر مشكلة في [1]. لنعد إلى العلامة:


<s:textfield name="double2" key="double2.prompt" value="%{getText('double.format',{double2})}"/>

عند العرض الأولي، تكون قيمة النموذج double2 هي null، وهي قيمة غير رقمية. نقوم بتعديل العلامة على النحو التالي:


<s:textfield name="double2" key="double2.prompt" value="%{double2==null ? '' : getText('double.format',{double2})}"/>

هذه المرة، نختبر ما إذا كانت القيمة هي double2==null. إذا كانت الإجابة نعم، نعرض سلسلة فارغة.

بعد إجراء هذا التغيير، نستأنف الاختبارات:

تُظهر الشاشات من [1] إلى [4] أن المشكلة التي كنا نسعى لحلها قد حُلّت:

  • في الشاشة [1]، يتم إدخال الرقم 4,67
  • في الشاشة [2]، تم قبول هذا الرقم
  • في [3]، يُعرض الرقم مرة أخرى على أنه 4,67 مع الفاصلة، وهو ما تؤكده [4].

لسوء الحظ، لا تتوقف المشاكل عند هذا الحد. لنلقِ نظرة على التسلسل التالي:

  • في [5]، تمت إضافة حرف لإبطال صحة double2
  • في [6]، أدت اختبارات التحقق من الصحة دورها وتم الإبلاغ عن الخطأ. إلا أن السلسلة المعروضة في [6] ليست السلسلة الخاطئة، بل القيمة الحالية للنموذج double2. لقد فقدنا القيمة التي تم إدخالها.

عند الانتقال من [5] إلى [6]، لا تكتمل العملية. يتم إيقافها بواسطة مانع التحقق من الصحة. في [6]، تم عرض قيمة النموذج double2 الذي لم يتلقَ قيمة جديدة بسبب هذا التوقف. وبالتالي، يتم عرض قيمته السابقة في حين كان ينبغي عرض السلسلة التي تم إدخالها. يمكن الاطلاع على معلمات الطلب عبر الترميز #parameters['param']. يتم تعديل حقل الإدخال double2 بالطريقة التالية:


      <s:textfield name="double2" key="double2.prompt" value="%{#parameters['double2']!=null ? #parameters['double2'] : double2==null ? '' : getText('double.format',{double2})}"/>

يتم حساب القيمة المعروضة لحقل double2 على النحو التالي: إذا كان المعلمة 'double2' موجودة، يتم عرضها، وإلا يتم عرض النموذج double2. يُطلب من القارئ اختبار ما إذا كانت هذه النسخة الجديدة من العلامة تحل المشكلات التي تمت مواجهتها.

13.10. Conclusion

من المدهش أن إدخال الأعداد الحقيقية مع التحقق من صحتها أمر معقد إلى هذا الحد... ربما فاتني شيء ما في الوثائق؟