لغة التعبير (EL)
لغة التعبير (EL)
قبل وجود لغة التعبير (EL)، كان مطوّرو JSP يطبعون خصائص الـ bean بكتابة scriptlets من قبيل <%= ((User) request.getAttribute("user")).getName() %>. كان هذا النهج يخلط تحويلات Java واستدعاءات الدوال مباشرةً داخل الصفحة، مما جعل القوالب هشّة وصعبة القراءة. قُدِّمت EL في JSTL 1.0 ثم أُدرجت كجزء من مواصفة Servlet/JSP (Jakarta EL، الإصدار 5.0 حاليًا). واليوم هي الطريقة الوحيدة التي ينبغي بها إخراج البيانات الديناميكية في صفحة JSP.
بنية ${...} — الأساسيات
كل تعبير EL محاط بـ ${ ... }. عند تصيير الصفحة يُقيّم الحاوي التعبير ويكتب النتيجة كسلسلة نصية. إذا كانت النتيجة null فتُخرج EL سلسلة فارغة بصمت — ولا ترمي NullPointerException.
#{ ... } في Jakarta Faces (JSF). في JSP العادية، التزم بـ ${ ... }. يتصرف الشكلان بالطريقة نفسها في سياقات EL للقراءة فقط داخل JSP، لكن #{ } تحمل معنى خاصًا في أُطر عمل المكوّنات.
كيف تحلّ EL الأسماء — سلسلة النطاقات
حين تصادف EL اسمًا مجرّدًا مثل ${product} تبحث عن سمة اسمها product بهذا الترتيب: page → request → session → application. أول تطابق يفوز. يعكس هذا الكائنات الضمنية التي تُعيّنها بـ request.setAttribute() وsession.setAttribute() وغيرها. يمكنك التصريح الصريح باستخدام خرائط النطاق المدمجة:
فضّل الشكل الصريح دائمًا حين يمكن أن يظهر الاسم نفسه في نطاقات متعددة — فذلك يجعل الصفحة موثّقة ذاتيًا ويتفادى أخطاء التظليل الخفية.
قراءة خصائص الـ Bean
تستخدم EL عامل النقطة للتنقّل عبر خصائص JavaBean. ${user.name} تستدعي user.getName() — تتبع EL اصطلاح JavaBeans (احذف اسم الخاصية، حوّل أوله إلى حرف كبير، أضف "get"). الخصائص المنطقية تستخدم is: ${product.available} تستدعي product.isAvailable().
التنقّل المتسلسل (user.address.company) يواصل الاجتياز طالما أن كل خطوة تُعيد كائنًا غير null. أي null في أيّ مكان بالسلسلة يوقف الاجتياز ويُعيد سلسلة فارغة بدلًا من رمي استثناء.
عامل الأقواس — المجموعات والمفاتيح الديناميكية
عامل الأقواس ${expr[key]} أقوى من عامل النقطة لأن المفتاح يمكن أن يكون بدوره تعبيرًا. يعمل على الخرائط والقوائم والمصفوفات والـ beans:
العوامل داخل تعبيرات EL
تدعم EL مجموعة ثرية من العوامل كي تحسب القيم وتُشكّل الشروط مباشرةً في الصفحة دون اللجوء إلى scriptlets.
- حسابية:
+،-،*،/(أوdiv)،%(أوmod) - علائقية:
==(أوeq)،!=(أوne)،<(lt)،>(gt)،<=(le)،>=(ge) - منطقية:
&&(أوand)،||(أوor)،!(أوnot) - ثلاثية:
condition ? valueIfTrue : valueIfFalse - اختبار الفراغ:
empty expr— صحيح إذا كانت القيمة null أو سلسلة فارغة أو مصفوفة فارغة أو مجموعة فارغة - الإسناد (EL 3.0+):
=— نادر الاستخدام في صفحات JSP العادية، لكنه متاح
الكائنات الضمنية في EL
تعرض EL مجموعة من الخرائط للقراءة فقط ككائنات ضمنية، تشبه المتغيرات الضمنية في scriptlet لكنها أكثر ملاءمة:
param— معامل الطلب بالاسم، مثل${param.q}paramValues— معاملات الطلب متعددة القيم (تُعيدString[])header/headerValues— رؤوس طلب HTTPcookie— خريطة كائناتCookie؛ استخدم${cookie.JSESSIONID.value}initParam— معاملات تهيئة سياق servlet منweb.xmlpageContext— كائنPageContextالكامل، يمنح وصولًا إلى الطلب والاستجابة والجلسة والمزيد
استدعاء الدوال الثابتة والبانيات (EL 3.0+)
تتيح Jakarta EL 3.0 (Servlet 3.1 / Tomcat 8+) استدعاء الدوال الثابتة إذا استوردتَ الفئة أولًا عبر واجهات importClass أو importStatic. عمليًا، الاستخدام الأكثر شيوعًا هو من خلال دوال الأدوات المسجّلة عبر مكتبة دوال JSTL — وهذا يُغطَّى في الدرس التالي. في الوقت الراهن، اعلم أن EL تستطيع استدعاء أدوات مساعدة بأسلوب String.format حين تُوصَّل بشكل صحيح، لكن هذا التوصيل يكون في مكتبة الوسوم لا في EL الخام.
تركيب EL مع سمات HTML
تتألف تعبيرات EL بسلاسة داخل قيم سمات HTML. هنا يظهر تفوّقها على scriptlets:
fn:escapeXml() عند تصييرها في سمات HTML أو المحتوى. لا تُفلت EL المخرجات افتراضيًا. تصيير ${param.search} مباشرةً في سمة ثغرة XSS. دالة fn:escapeXml جزء من مكتبة دوال JSTL التي تُغطَّى في الدرس السادس.
الخلاصة
تمنح لغة التعبير صفحات JSP طريقةً نظيفة وآمنة من حيث القيم الخالية لقراءة السمات ذات النطاق والتنقّل عبر خصائص الـ bean والوصول إلى المجموعات بالفهرس أو المفتاح وحساب الشروط البسيطة — كل ذلك دون سطر Java واحد من الـ scriptlet. تمنحك سلسلة النطاقات (page → request → session → application) وخرائط النطاق الصريحة تحكمًا دقيقًا في مصدر البيانات. استخدم عامل النقطة للـ beans، والأقواس للخرائط والقوائم، وكلمة empty للفحوصات الآمنة من القيم الخالية، والأسماء المستعارة (lt، gt، and) لإبقاء قيم السمات HTML صالحة. في الدرس التالي ستُضيف JSTL Core Tags فوق EL للتعامل مع التكرار والتفريع بشكل تصريحي.