وداعًا لكود السباغيتي: كيفية إزالة Java من JSP نهائيًا
\n\nإذا سبق لك فتح ملف JSP قديم ورأيت خليطًا من HTML و <% %> scriptlets ومنطق Java، فأنت تعرف هذا الشعور. مزيج العرض ومنطق الأعمال يحول صيانة المشروع إلى جحيم. سؤال "How can I avoid Java code in JSP files, using JSP 2?" على Stack Overflow حصل على آلاف المشاهدات - وليس بدون سبب.
الخبر السار: JSP 2 (Java Server Pages الإصدار 2) أعطانا أدوات لننسى scriptlets إلى الأبد. في هذه المقالة، سأعرض ثلاث طرق عملية ستحول JSP الخاصة بك إلى قوالب نظيفة وقابلة للقراءة. لا ماء - فقط كود وتطبيق عملي.
\n\nلماذا scriptlets شريرة؟ نظرة مطور
\n\nScriptlets (تلك <% ... %>) تنتهك المبدأ الأساسي لـ MVC: فصل المنطق والعرض. إليك ثلاثة أسباب للتخلص منها:
- \n
- صعوبة الصيانة. عندما يحتوي JSP على استعلامات SQL وعبارات شرطية، لا يمكن للمصمم تعديل التخطيط بأمان. \n
- صعوبة الاختبار. لا يمكن اختبار المنطق داخل JSP باستخدام unit tests. \n
- ضعف readability. يتحول الكود إلى "سباغيتي" حيث يختلط Java مع HTML. \n
يقدم JSP 2 بدائل أنيقة. دعنا نناقشها من خلال مثال حقيقي: عرض قائمة المستخدمين من قاعدة البيانات.
\n\nالطريقة 1: Expression Language (EL) - صديقك الجديد
\n\nExpression Language (EL) يتيح الوصول إلى كائنات Java مباشرة في JSP دون سطر واحد من كود Java. الصيغة ${...} بديهية وسهلة الفهم.
كان (مع كود Java):
\n\n<% \n User user = (User) request.getAttribute("user"); \n out.println("مرحبًا، " + user.getName());\n%>\n\nأصبح (مع EL):
\n\n<p>مرحبًا، ${user.name}</p>\n\nEL يستدعي تلقائيًا دوال getter. إذا كان user.getName() يُرجع سلسلة نصية - سيتم إدراجها في HTML. إذا كان الكائن null - لن يُخرج EL شيئًا (بدون NullPointerException).
أين تستخدم: لعرض البيانات من request و session و application scope أو معاملات الطلب.
\n\nالطريقة 2: JSTL (JSP Standard Tag Library) - حلقات وشروط بدون Java
\n\nJSTL هي مجموعة من الوسوم الجاهزة التي تغطي 90% من المهام النمطية: الحلقات، الشروط، التنسيق، العمل مع URL. للتوصيل، يكفي إضافة التبعية في pom.xml (Maven) أو تحميل JAR.
مثال: عرض قائمة المستخدمين في جدول.
\n\nقبل (scriptlets):
\n\n<table>\n <%\n List<User> users = (List<User>) request.getAttribute("users");\n for (User u : users) {\n %>\n <tr><td><%= u.getName() %></td><td><%= u.getEmail() %></td></tr>\n <%\n }\n %>\n</table>\n\nبعد (JSTL + EL):
\n\n<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>\n<table>\n <c:forEach var="u" items="${users}">\n <tr>\n <td>${u.name}</td>\n <td>${u.email}</td>\n </tr>\n </c:forEach>\n</table>\n\nلاحظ: لا يوجد سطر واحد من Java! الوسم <c:forEach> يعمل كحلقة foreach، و ${u.name} هو تعبير EL. أصبح الكود قابلًا للقراءة وآمنًا.
وسوم JSTL مفيدة أخرى:
\n- \n
<c:if test="${condition}">- عرض شرطي \n <c:choose>- بديل لـ switch \n <c:set var="x" value="..." />- إنشاء متغير \n <fmt:formatDate>- تنسيق التواريخ \n