مقدمة إلى JSP
مقدمة إلى JSP
JavaServer Pages — أو JSP اختصارًا — هي تقنية من جانب الخادم تُتيح لك تضمين منطق Java مباشرةً داخل ترميز HTML. تُنتج ملف قالب يُترجمه الخادم إلى Servlet كامل، يُنفِّذه ثم يُرسل استجابته إلى المتصفح بوصفها HTML عادية. إنّ فهم سبب اختراع JSP — وما يحدث بالضبط بين ملف .jsp واستجابة HTTP — هو الأساس المفاهيمي لكل ما يلي في هذا البرنامج التعليمي.
المشكلة التي صُمِّمت JSP لحلّها
قبل وجود JSP، كان إنتاج محتوى ويب ديناميكي في Java يعني كتابة Servlet: فئة Java عادية تستجيب لطلبات HTTP. تعمل Servlets بشكل ممتاز، لكن توليد HTML من داخل تابع Java أمر مُربك:
أي تغيير في HTML يستلزم إعادة تصريف ونشر الكود. مصمم يفهم HTML لكنه لا يعرف Java لا يستطيع تعديل الملف بأمان. السلاسل يصعب قراءتها، ولا تستطيع أدوات التطوير تمييز الترميز بألوان، والكود مقترن بشدة بتفاصيل العرض التي تتغير كثيرًا أكثر من المنطق التجاري.
تعكس JSP هذه العلاقة: تكتب HTML أولًا، وتُدرج جُزرًا صغيرة من Java حيثما تحتاج إلى محتوى ديناميكي.
JSP مقابل Servlets — شريكان لا منافسان
تحلّ JSP و Servlets نصفَي المشكلة ذاتها. يُخصّص النمط الناضج (MVC الذي تتناوله الدرس السابع) لكلٍّ منهما دوره المناسب:
- Servlet — يعالج الطلب، يتحقق من المدخلات، يستدعي الخدمات/المستودعات، يضع النتائج في سمات الطلب، ثم يُعيد التوجيه إلى JSP.
- JSP — تقرأ تلك السمات وتُصيِّر HTML. لا تحتوي على منطق أعمال، ولا استدعاءات قاعدة بيانات، ومن المثالي ألّا تضمّ أي كتل برمجية Java خام.
كيف يتحوّل ملف JSP إلى Servlet
حين يصل طلب للحصول على products.jsp، يُشغِّل حاوي Jakarta EE (Tomcat أو WildFly أو GlassFish وغيرها) الملف عبر خط أنابيب محدد. إنّ فهم هذا الخط يُزيل الغموض عن رسائل الخطأ ويُخبرك متى تُعاد عملية التصريف.
- مرحلة الترجمة — يقرأ الحاوي مصدر
.jspويولّد ملف مصدر Java. هذا الملف هو فئة تمتد منjakarta.servlet.http.HttpJspBase، التي تمتد بدورها منHttpServlet. يتحوّل ترميز HTML إلى سلسلة من استدعاءاتout.write("<p>...");؛ أما تعبيرات Java المضمّنة فتصبح تعليمات إخراج مباشرة. - مرحلة التصريف — يُصرِّف الحاوي مصدر Java المولَّد إلى ملف
.classباستخدام مُصرِّف Java المدمج (javac). إذا كان كود Java المضمَّن خاطئًا نحويًا، فسترى خطأ تصريفٍ هنا، كثيرًا ما يتضمن رقم سطر يُشير إلى المصدر المولَّد لا إلى JSP الأصلية — وهذا ما يجعل رسائل أخطاء JSP محيِّرةً في البداية. - التحميل والتهيئة — يُحمَّل الملف المُصرَّف في JVM ويُنشأ منه كائن تمامًا كأي Servlet آخر. تُستدعى
jspInit()مرة واحدة. - معالجة الطلبات — لكل طلب لاحق، تُستدعى
_jspService(HttpServletRequest, HttpServletResponse)على الكائن القائم. يحتوي هذا التابع على كل كود الإخراج المولَّد. - التخزين المؤقت — يُخزِّن الحاوي الفئة المُصرَّفة مؤقتًا. عند الطلب التالي يتحقق مما إذا كان مصدر
.jspأحدث من الفئة المُصرَّفة؛ إن لم يكن كذلك تجاوز مرحلتَي الترجمة والتصريف كليًا. لهذا تحتاج معظم الحاويات إلى إخطارها بالتحديثات في الإنتاج (أو تضبطdevelopment="false"فيconf/web.xmlالخاص بـ Tomcat لتعطيل فحص الطابع الزمني بأكمله من أجل الأداء).
يُترجم الحاوي تلك الصفحة إلى شيء مكافئ هيكليًا لما يلي:
$CATALINA_HOME/work/Catalina/localhost/<app>/. قراءة الملف المولَّد عند حدوث خطأ غامض كثيرًا ما تكون أسرع طريقة لفهم المشكلة — فأرقام الأسطر في stack trace تُشير إلى ذلك الملف المولَّد.
دورة حياة JSP باختصار
بما أن JSP هي في نهاية المطاف Servlet، فإن دورة حياتها تُعكس دورة حياة Servlet:
jspInit()— تُستدعى مرة واحدة بعد تحميل الفئة. يمكنك تجاوزها في كتلة تصريح JSP لإعداد الموارد (نادرًا ما يُحتاج إليه)._jspService()— تُستدعى لكل طلب. هذا ما تكتبه فعليًا حين تؤلّف جسم JSP. لا يمكنك تجاوزها مباشرةً — الحاوي يُولِّدها.jspDestroy()— تُستدعى مرة واحدة عند إيقاف تشغيل الحاوي أو إعادة تحميل JSP. أتلف أي موارد تهيّأت فيjspInit().
_jspService()، أو سمات الجلسة. هذا هو ذات الفخ الموجود في Servlets العادية.
مكانة JSP اليوم
كثيرًا ما تستبدل تطبيقات Jakarta EE و Spring الحديثة JSP بـ Thymeleaf أو FreeMarker أو واجهة أمامية بـ JavaScript. ومع ذلك تظل JSP تقنية العرض الأساسية المدرَّسة في مواصفة Jakarta EE، ولا تزال كميات هائلة من كود Java المؤسسي تستخدمها. كذلك يمنحك فهم JSP بعمق نموذجًا ذهنيًا دقيقًا لطريقة عمل أي محرك قوالب من جانب الخادم: جميعها في نهاية المطاف تُنتج تدفقًا من الحروف إلى Writer، وتستخدم شكلًا من أشكال تقييم التعبيرات لإدراج القيم الديناميكية. المفاهيم التي ستتعلمها هنا تنتقل مباشرةً إلى تلك التقنيات.
الخلاصة
وُجدت JSP لأن كتابة HTML داخل كود Servlet في Java عُرضة للأخطاء وصعبة الصيانة. ملف JSP هو HTML يحتوي على أجزاء Java مضمَّنة؛ يُترجمه الحاوي ويُصرِّفه إلى Servlet كامل خلف الكواليس. يُفسِّر خط أنابيب الترجمة-التصريف-التخزين المؤقت لماذا تُشير رسائل خطأ JSP أحيانًا إلى ملفات مصدر مولَّدة، ولماذا لا تعكس الصفحة تغييرًا ما لم يُعد الحاوي تصريفها. JSP و Servlets شريكان: تتولى Servlets تدفق التحكم والوصول إلى البيانات، وتتولى JSP التصيير. في الدرس التالي ستستكشف عناصر النصوص البرمجية الثلاثة في JSP — التصريحات، والكتل البرمجية، والتعبيرات — التي تُتيح لك تضمين Java داخل ترميز HTML ذاك.