Skip to content

16. تطبيق الويب MVC في بنية ثلاثية الطبقات – المثال 2

16.1. مقدمة

لقد كتبنا التطبيق [personnes-01] الذي له الهيكل التالي:

قامت الطبقة [dao] بتنفيذ قائمة الأشخاص التي تتم إدارتها باستخدام كائن [ArrayList]. وقد سمح لنا ذلك بعدم الإسهاب في الحديث عن الطبقتين [dao] و [service] للتركيز على الطبقة [web]. نرغب في تطوير التطبيق نحو بيئة أكثر واقعية حيث يتم تخزين قائمة الأشخاص في جدول قاعدة بيانات. سيؤدي ذلك إلى تغيير الطبقة [dao]. وسيؤثر ذلك على الطبقتين الأخريين. للاستفادة من استقلالية الطبقات التي يوفرها Spring IoC، سنستأنف التطبيق [personnes-01] ونقوم بتكوينه باستخدام Spring IoC:

سيُسمى التطبيق الجديد [personnes-02]. بمجرد كتابته، نعلم أنه سيكون بإمكاننا تغيير الطبقتين [dao] و [service] دون تغيير كود الطبقة [web]. وهذا هو ما نسعى إليه.

نقوم بإنشاء مشروع Eclipse جديد [personnes-02] عن طريق نسخ/لصق مشروع [personnes-01] كما تم شرحه في الفقرة 6.2:

في [1]، نرى ظهور ملف التكوين الذي سنقوم فيه بتعريف حبات الطبقات [dao] و [service]. ومحتواه كما يلي:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- فئة dao -->
    <bean id="dao" class="istia.st.mvc.personnes.dao.DaoImpl" init-method="init"/>
    <!-- فئة الخدمة -->
    <bean id="service" class="istia.st.mvc.personnes.service.ServiceImpl">
        <property name="dao">
            <ref local="dao" />
        </property>
    </bean>
</beans>
  • السطر 5: يحدد bean المسمى [dao] كمثيل للفئة [DaoImpl]. بعد إنشاء المثيل، يتم تنفيذ الطريقة [init] للمثيل.
  • الأسطر 7-10: تحدد الكائن المسمى [service] كمثيل للفئة [ServiceImpl].
  • الأسطر 8-10: يتم تهيئة الخاصية [dao] للمثيل [DaoImpl] باستخدام مرجع الطبقة [dao] التي تم إنشاؤها في السطر 5. تجدر الإشارة إلى أن الفئة [ServiceImpl] تحتوي بالفعل على الخاصية [dao] ومُعيّنها المرتبط بها:
public class ServiceImpl implements IService {

    // الطبقة [dao]
    private IDao dao;

    public IDao getDao() {
        return dao;
    }

    public void setDao(IDao dao) {
        this.dao = dao;
    }
...

بالطبع، هذا الملف وحده لا يفعل شيئًا. سيستخدمه المتحكم [Application] في طريقة [init] لإنشاء مثيل للطبقة [service]. لنتذكر الإصدار السابق من طريقة [init] الخاصة بوحدة التحكم:

@SuppressWarnings("serial")
public class Application extends HttpServlet {
...
    // الخدمة
    ServiceImpl service = null;

    // التشغيل
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
        // إنشاء مثيل للطبقة [dao]
        DaoImpl dao = new DaoImpl();
        dao.init();
        // إنشاء مثيل للطبقة [service]
        service = new ServiceImpl();
        service.setDao(dao);
    }

في السطر 5، اضطررنا إلى تسمية فئة تنفيذ الطبقة [service] بشكل صريح، وفي السطر 12، فئة الطبقة [dao]. مع Spring IoC، تصبح الطريقة [init] كما يلي:

@SuppressWarnings("serial")
public class Application extends HttpServlet {
    // معلمات المثيل
    ...

    // الخدمة
    private IService service = null;

    // التشغيل
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
    ...
        // إنشاء مثيل الطبقة [service]
        service = (IService) new XmlBeanFactory(new ClassPathResource("spring-config.xml")).getBean("service");
    }
  • السطر 7: لم يعد الحقل الخاص [service] من النوع [ServiceImpl] بل من النوع [IServicec.a.d. من نوع واجهة الطبقة [service]. وبالتالي، لم تعد الطبقة [web] مرتبطة بتنفيذ معين لهذه الواجهة.
  • السطر 14: تهيئة الحقل [service] من ملف التكوين [spring-config.xml].

هذه هي التعديلات الوحيدة التي يجب إجراؤها. لنقم بدمج هذا التطبيق الجديد في Tomcat، ونقوم بتشغيله ثم نطلب عنوان URL [http://localhost:8080/personnes-02]:

Image

16.2. أرشفة تطبيق الويب

لقد قمنا بتطوير مشروع Eclipse / Tomcat لتطبيق ثلاثي الطبقات:

في إصدار قادم، سيتم وضع مجموعة الأشخاص في جدول قاعدة بيانات.

  • سيؤدي ذلك إلى إعادة كتابة الطبقة [dao]. وهذا أمر يسهل فهمه.
  • سيتم أيضًا تعديل الطبقة [service]. حاليًا، يتمثل دورها الوحيد في ضمان الوصول المتزامن إلى البيانات التي تديرها الطبقة [dao]. ولهذا الغرض، قمنا بمزامنة جميع أساليب الطبقة [service]. لقد أوضحنا سبب وضع هذه المزامنة في هذه الطبقة بدلاً من الطبقة [dao]. في الإصدار الجديد، ستظل الطبقة [service] تؤدي الدور الوحيد المتمثل في مزامنة الوصول، ولكن سيتم ضمان ذلك من خلال معاملات قاعدة البيانات بدلاً من مزامنة طرق Java.
  • أما الطبقة [web] فستبقى دون تغيير.

لتسهيل الانتقال من إصدار إلى آخر، نقوم بإنشاء مشروع Eclipse جديد [mvc-personnes-02B]، وهو نسخة من المشروع السابق [mvc-personnes-02]، ولكن تم وضع الطبقات [web, service, dao, entites] في أرشيفات .jar:

لا يحتوي المجلد [src] الآن سوى على ملف تكوين Spring [spring-config.xml]. كان يحتوي في السابق أيضًا على كود مصدر فئات Java. وقد اختفت هذه العناصر، وحل محلها العناصر المُجمَّعة الموضوعة في أرشيفات [personnes-*.jar] الموضحة في [1]:

تم تكوين المشروع [mvc-personnes-02B] ليشمل الأرشيفات [personnes-*.jar ] في ملفه ClassPath.

نقوم بنشر مشروع الويب [mvc-personnes-02B] داخل Tomcat:

لاختبار المشروع، نقوم بتشغيل Tomcat ثم نطلب عنوان URL [http://localhost:8080/personnes02B]:

Image

يُطلب من القارئ إجراء اختبارات إضافية.

في الإصدار الذي يحتوي على قاعدة بيانات، سنقوم بتغيير الطبقات [service] و [dao]. نريد أن نوضح أنه يكفي عندئذٍ استبدال الأرشيفات [personnes-dao.jar] و [personnes-service.jar] في المشروع السابق بالأرشيفات الجديدة حتى يعمل تطبيقنا من الآن فصاعدًا مع قاعدة بيانات. ولن نضطر إلى المساس بأرشيفات الطبقة [web] والطبقة [entites].