وسوم JSTL الأساسية
وسوم JSTL الأساسية
من أبرز أخطاء تطوير JSP في مراحله الأولى كان دمج كود Java مباشرةً داخل ملفات العرض (View) باستخدام Scriptlets. كان الناتج قوالبَ يستحيل تسليمها إلى مصمم، وعسيرة الاختبار، وهشّة في الصيانة. جاءت مكتبة وسوم JSP القياسية (JSTL) تحديداً لحل هذه المشكلة عبر استبدال Scriptlets بمجموعة من الوسوم شبيهة بـ XML. تغطّي مكتبة Core — ذات البادئة c: — الاحتياجات اليومية: الشروط، والتكرار، والمتغيرات ذات النطاق. أتقن هذه الوسوم الأربعة وستصبح ملفات JSP لديك مقروءة وقابلة للاختبار وودية للتصميم.
إضافة JSTL إلى مشروعك
JSTL ليست جزءاً من مواصفات Jakarta EE Servlet؛ بل تحتاج إلى إضافة ملف JAR للتنفيذ. مع Maven:
ثم أعلن عن مكتبة الوسوم Core في أعلى كل ملف JSP يستخدمها:
jakarta.tags.core. على المشاريع القديمة مع Tomcat 9 أو Java EE يكون URI هو http://java.sun.com/jsp/jstl/core. تأكد دائماً من مطابقة إصدار JSTL لإصدار حاوية الـ Servlet.
c:set — تخزين القيم في النطاق
يُعدّ <c:set> البديل الـ JSTL لتعريف المتغيرات في الـ Scriptlet. يخزّن قيمة في أحد نطاقات JSP الأربعة: page أو request أو session أو application. النطاق الافتراضي هو page.
من الأنماط المفيدة جداً استخدام c:set لإنشاء اسم بديل (alias) لخاصية متداخلة بعمق، حتى لا تضطر لتكرار مسار EL الكامل في كل أنحاء الصفحة.
c:set كاسم بديل: إن كنت تشير إلى ${order.customer.billingAddress.city} خمس مرات في الصفحة، عرّفه مرة واحدة — <c:set var="city" value="${order.customer.billingAddress.city}"/> — ثم استخدم ${city}. أقصر وأسرع (تقييم EL واحد) وأسهل في إعادة التسمية.
c:if — الشروط البسيطة
يعرض <c:if> محتواه الداخلي فقط عندما يُقيَّم الخاصية test بالقيمة true. وهو الشرط الأحادي الفرع البسيط.
لاحظ عمليات EL: empty تتحقق من القيمة null أو المجموعة/النص الفارغ، وnot empty هي عكسها، وgt تعني أكبر من، وeq تعني يساوي. يُجنّبك استخدام هذه المشغّلات النصية الحاجةَ إلى هروب < و> داخل XML/HTML.
c:if فرعاً else. إن احتجت بنية if/else، فأنت تحتاج c:choose. استخدام شرطَي c:if متعاكسَين هش — لو تغيّر الشرط عليك تحديث كلا الوسمَين وتخاطر بإدخال ثغرة أو تداخل.
c:choose — الشروط متعددة الفروع
يُعدّ <c:choose> مع <c:when> و<c:otherwise> المتداخلة المكافئ الـ JSTL لسلسلة switch/if-else. يُعرض فقط أول فرع when متطابق؛ أما otherwise فهو الاحتياطي حين لا يتطابق شيء.
يؤدي فرع c:otherwise غرضاً مزدوجاً: يعرض قيمة افتراضية معقولة، ويعمل شبكةَ أمان حين تُضاف قيم enum جديدة في الكود الخلفي دون وجود c:when مقابل. أدرجه دائماً.
c:forEach — التكرار
يُعدّ <c:forEach> المكرّر في JSTL. يعمل على أي java.lang.Iterable والمصفوفات وإدخالات Map والنصوص المفصولة بفاصلة. وهو الوسم الأكثر استخداماً في تطبيقات الويب النموذجية.
عرض قائمة أساسي:
الخاصية varStatus تكشف كائن حالة الحلقة مع خصائص مفيدة:
خصائص varStatus بإيجاز:
index— الفهرس الصفري للتكرار الحاليcount— العداد الذي يبدأ من 1 (index + 1)، مثالي لترقيم الصفوفfirst— قيمة منطقية، تكون true في أول تكرارlast— قيمة منطقية، تكون true في آخر تكرار
التكرار على مدى أعداد صحيحة (دون الحاجة إلى مجموعة):
التكرار على Map:
الجمع بين الوسوم: مثال كامل
تجمع ملفات JSP الحقيقية بين هذه الوسوم الأربعة جميعاً. إليك مقتطفاً واقعياً من صفحة قائمة المنتجات يوضح كيف يضع Servlet البيانات في الطلب ثم يعرضها ملف JSP دون scriptlet واحد:
${products.size() gt 0} تعمل، لكن ${not empty products} هو الأسلوب الاصطلاحي في JSTL ويتعامل مع null بأمان — فـsize() على مرجع null تُلقي NullPointerException.
لماذا تنتمي هذه الوسوم إلى كل ملف JSP
تُنفّذ هذه الوسوم الأربعة مبدأ العرض الخالي من المنطق: قرارات العمل (ما البيانات التي تعرضها، كيف تحسب المجموع) تنتمي إلى طبقة Servlet أو الخدمة؛ مهمة JSP الوحيدة هي عرض حالة معطاة. تعبّر c:if/c:choose عن قرارات العرض مثل "أظهر رسالة الحالة الفارغة" أو "أضف فئة CSS عندما يكون هذا أول عنصر". يعرض c:forEach المجموعات التي جهّزها المتحكم. يُنشئ c:set أسماء بديلة محلية للحفاظ على قابلية قراءة القالب. معاً تتيح هذه الوسوم لمصمم تعديل HTML دون لمس أي Java، وتتيح لمطوّر اختبار وحدة كل المنطق قبل كتابة العرض حتى.
الخلاصة
c:set— تعريف متغير ذي نطاق أو اسم بديل؛ يُلغي تعريفات الـ Scriptlet<% %>.c:if— شرط أحادي الفرع؛ استخدمه حين تحتاج فقط حارساً إيجابياً.c:choose/c:when/c:otherwise— شرط متعدد الفروع؛ البديل النظيف لأزواجc:ifالمتتالية.c:forEach— التكرار على أي مجموعة أو مصفوفة أو Map أو مدى صحيح؛ استخدمvarStatusللفهرس والعداد وعلامتَي first/last.
في الدرس القادم ستوسّع JSTL بمكتبتَي وسوم Formatting وFunctions للتعامل مع التواريخ والأرقام ومعالجة النصوص — للإبقاء على منطق التنسيق خارج كود Java أيضاً.