Skip to content

16. برنامه وب MVC در معماری سه‌لایه – مثال ۲

16.1. Introduction

ما برنامه [personnes-01] را با ساختار زیر نوشته‌ایم:

لایه [dao] فهرست افرادی را که با استفاده از یک شیء [ArrayList] مدیریت می‌شوند، پیاده‌سازی کرد. این امر به ما امکان داد تا از تمرکز بر لایه‌های [dao] و [service] اجتناب کنیم تا بتوانیم بر لایه [web] تمرکز کنیم. ما می‌خواهیم برنامه را به سمت یک محیط واقع‌گرایانه‌تر توسعه دهیم که در آن فهرست افراد در یک جدول پایگاه داده ذخیره شود. این امر مستلزم اصلاح لایه [dao] است. این تغییر بر دو لایه دیگر نیز تأثیر خواهد گذاشت. برای بهره‌مندی از استقلال لایه‌ای که Spring IoC فراهم می‌کند، ما برنامه [personnes-01] را برداشته و آن را با Spring IoC پیکربندی خواهیم کرد:

برنامه جدید [personnes-02] نام‌گذاری خواهد شد. پس از نوشتن آن، می‌دانیم که قادر خواهیم بود لایه‌های [dao] و [service] را بدون تغییر کد در لایه [web] تغییر دهیم. این همان چیزی است که ما به دنبال آن هستیم.

ما یک پروژه جدید اکلیپس به نام [personnes-02] را با کپی و پیست از پروژه [personnes-01] ایجاد می‌کنیم، همان‌طور که در بخش 6.2 توضیح داده شده است:

در [1]، می‌توانیم فایل پیکربندی را ببینیم که در آن، بیین‌ها (beans) را برای لایه‌های [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>
  • خط ۵: بیانهٔ bean با نام [dao] را به‌عنوان نمونه‌ای از کلاس [DaoImpl] تعریف می‌کند. پس از نمونه‌سازی، متد [init] این نمونه اجرا می‌شود.
  • خطوط ۷–۱۰: دانه با نام [service] به‌عنوان نمونه‌ای از کلاس [ServiceImpl] تعریف می‌شود.
  • خطوط ۸–۱۰: ویژگی [dao] از نمونه [DaoImpl] با ارجاع به لایه [dao] که در خط ۵ ایجاد شده است، مقداردهی اولیه می‌شود. شایان ذکر است که کلاس [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;

     // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
         // نمونه سازی لایه [dao]
        DaoImpl dao = new DaoImpl();
        dao.init();
         // مثال‌سازی لایه [service]
        service = new ServiceImpl();
        service.setDao(dao);
    }

در خط ۵، مجبور بودیم کلاس پیاده‌سازی لایه [service] را صراحتاً نام‌گذاری کنیم، و در خط ۱۲، کلاس پیاده‌سازی لایه [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");
    }
  • خط ۷: فیلد خصوصی [service] دیگر از نوع [ServiceImpl] نیست بلکه از نوع [IServicec.a.d است. از نوع رابط لایه [service]. بنابراین لایه [web] دیگر به پیاده‌سازی خاصی از این رابط مرتبط نیست.
  • خط ۱۴: مقداردهی اولیه فیلد [service] از فایل پیکربندی [spring-config.xml].

این تنها تغییرات مورد نیاز هستند. بیایید این برنامه جدید را در Tomcat مستقر کنیم، آن را راه‌اندازی کنیم و سپس URL [http://localhost:8080/personnes-02] را درخواست کنیم:

Image

16.2. آرشیو کردن برنامه وب

ما یک پروژه Eclipse/Tomcat برای یک برنامه سه‌لایه توسعه داده‌ایم:

در نسخهٔ آینده، گروه افراد در یک جدول پایگاه داده ذخیره خواهد شد.

  • این امر مستلزم بازنویسی لایه [dao] خواهد بود. درک آن آسان است.
  • لایه [service] نیز اصلاح خواهد شد. در حال حاضر، تنها نقش آن تضمین دسترسی همگام به داده‌های مدیریت‌شده توسط لایه [dao] است. برای این منظور، ما تمام متدهای لایه [service] را همگام‌سازی کرده‌ایم. ما توضیح داده‌ایم که چرا این همگام‌سازی در این لایه و نه در لایه [dao] قرار داده شده است. در نسخه جدید، لایه [service] همچنان نقش انحصاری همگام‌سازی دسترسی را خواهد داشت، اما این کار به جای همگام‌سازی متدهای جاوا، از طریق تراکنش‌های پایگاه داده انجام خواهد شد.
  • لایه [web] بدون تغییر باقی خواهد ماند.

برای تسهیل انتقال از یک نسخه به نسخه بعدی، ما در حال ایجاد یک پروژه جدید اکلیپس به نام [mvc-personnes-02B] هستیم که کپی‌ای از پروژه قبلی، [mvc-personnes-02]، است، اما در آن لایه‌های [web, service, dao, entites] در آرشیوهای .jar قرار داده شده‌اند:

فولدر [src] اکنون فقط شامل فایل پیکربندی Spring به نام [spring-config.xml] است. قبلاً این پوشه همچنین حاوی کد منبع کلاس‌های جاوا بود. این عناصر حذف شده و نسخه‌های کامپایل‌شده آن‌ها که در آرشیو [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] نخواهیم داشت.