Skip to content

8. نسخهٔ ۴ – کلاینت/سرور در معماری سرویس وب

در این نسخهٔ جدید، برنامهٔ [Pam] در حالت کلاینت/سرور در چارچوب معماری سرویس وب اجرا خواهد شد. بیایید معماری برنامهٔ قبلی را مجدداً بررسی کنیم:

در بالا، یک لایه ارتباطی ([C, RMI, S]) ارتباط شفاف را بین کلاینت ([ui]) و لایه راه دور ([metier]) فعال می‌کرد. ما از معماری مشابهی استفاده خواهیم کرد، که در آن لایه ارتباطی [C, RMI, S] با لایه‌ای به نام [C, HTTP / SOAP, S] جایگزین خواهد شد:

پروتکل HTTP / SOAP نسبت به پروتکل قبلی RMI / EJB از مزیت چند سکویی بودن برخوردار است. این بدان معناست که سرویس وب می‌تواند به زبان جاوا نوشته شده و روی سرور GlassFish مستقر شود، در حالی که کلاینت می‌تواند یک کلاینت .NET یا PHP باشد.

ما این معماری را با استفاده از سه رویکرد مختلف توسعه خواهیم داد:

  1. سرویس وب توسط EJB [Metier] ارائه خواهد شد
  2. سرویس وب توسط یک برنامه وب با استفاده از EJB و [Metier] ارائه خواهد شد
  3. سرویس وب توسط یک برنامه وب با استفاده از Spring ارائه خواهد شد

یک سرویس وب می‌تواند به روش‌های مختلفی در یک سرور جاوا EE پیاده‌سازی شود:

  • با استفاده از کلاسی که با @WebService علامت‌گذاری شده و در یک کانتینر وب اجرا می‌شود
  • توسط یک EJB که با @WebService علامت‌گذاری شده و در یک کانتینر EJB اجرا می‌شود

ما با این معماری اخیر شروع خواهیم کرد.

8.1. سرویس وب پیاده‌سازی‌شده توسط یک EJB

8.1.1. سویٔل سرور

8.1.1.1. پروژه NetBeans

بیایید با ایجاد یک پروژه جدید Maven، یک نسخه کپی از پروژه EJB [mv-pam-ejb-metier-dao-jpa-eclipselink] شروع کنیم:

  

با معماری زیر:

لایه [metier] سرویس وبی خواهد بود که توسط لایه [ui] فراخوانی می‌شود. این کلاس نیازی به پیاده‌سازی یک رابط ندارد. این anotationها هستند که یک POJO (شیء جاوای معمولی) را به یک سرویس وب تبدیل می‌کنند. کلاس [Metier] که لایه [metier] را که در بالا توصیف شد پیاده‌سازی می‌کند، به شرح زیر تبدیل می‌شود:


package metier;

...
@WebService
@Stateless()
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class Metier implements IMetierLocal,IMetierRemote {
  
  //ارجاعات به لایه‌های [DAO]
  @EJB
  private ICotisationDaoLocal cotisationDao = null;
  @EJB
  private IEmployeDaoLocal employeDao=null;
  @EJB
  private IIndemniteDaoLocal indemniteDao=null;
  
  
  //بازیابی فیش حقوقی
@WebMethod
  public FeuilleSalaire calculerFeuilleSalaire(String SS,
...
  }
  
  // فهرست کارمندان
@WebMethod
   public List<Employe> findAllEmployes() {
...
  }
//مهم – هیچ گتر یا ستر برای EJB وجود ندارد
 }
  • خط ۴: حاشیه‌نویسی @WebService کلاس [Metier] را به یک سرویس وب تبدیل می‌کند. یک سرویس وب متدهایی را در معرض دید کلاینت‌های خود قرار می‌دهد. این متدها باید با ویژگی @WebMethod حاشیه‌نویسی شوند.
  • خطوط ۱۹ و ۲۵: دو متد کلاس [Metier] به متدهای سرویس وب تبدیل می‌شوند.
  • خط ۲۹: مهم است که گترها و سترها حذف شوند؛ در غیر این صورت، در سرویس وب در دسترس قرار خواهند گرفت که باعث خطاهای امنیتی می‌شود.

افزودن این حاشیه‌نویسی‌ها توسط NetBeans تشخیص داده می‌شود و سپس ماهیت پروژه را تغییر می‌دهد:

در [1]، یک ساختار درختی [Web Services] در پروژه ظاهر شده است. این ساختار شامل سرویس وب Metier و دو متد آن است. برنامه سرور را می‌توان به عنوان [2] مستقر کرد. سرور MySQL باید در حال اجرا باشد و پایگاه داده آن [dbpam_eclipselink] باید موجود و پر شده باشد. ممکن است برای جلوگیری از تداخل نام‌ها، لازم باشد ابتدا [3] و EJB را از پروژه کلاینت/سرور EJB که قبلاً بررسی شده بود، حذف کنید. این به این دلیل است که پروژه جدید ما شامل همان فایل‌های EJB پروژه قبلی است.

در [1]، می‌توانیم برنامه serveur خود را که روی سرور GlassFish مستقر شده است، مشاهده کنیم. پس از استقرار سرویس وب، می‌توان آن را آزمایش کرد:

  • در [1]، در داخل پروژهٔ جاری، سرویس وب [Metier] را آزمایش می‌کنیم
  • این سرویس وب از طریق URL قابل دسترسی است. URL و [2] به ما امکان می‌دهند سرویس وب را آزمایش کنیم
  • در [3]، لینکی به فایل XML که سرویس وب را تعریف می‌کند. مشتریان سرویس وب باید URL این فایل را بدانند. از همین URL است که لایه سمت مشتری (استاب‌ها) سرویس وب تولید می‌شود.
  • در [4,5]، فرم تست متدهای ارائه شده توسط سرویس وب قرار دارد. این متدها به همراه پارامترهایشان که کاربر می‌تواند آن‌ها را تعریف کند، نمایش داده می‌شوند.

برای مثال، بیایید روش [findAllEmployes] را که هیچ پارامتری ندارد، آزمایش کنیم:

 

در بالا، ما در حال آزمایش این متد هستیم. سپس پاسخ نشان داده شده در زیر (نمای جزئی) را دریافت می‌کنیم. این پاسخ در واقع دو کارمند را به همراه مزایای آن‌ها نشان می‌دهد. از خوانندگان دعوت می‌شود تا به همین ترتیب متد [4] را با ارسال سه پارامتر مورد انتظار آن آزمایش کنند.

Image

8.1.2. سمت کلاینت

8.1.2.1. project -console نت‌بینز کلاینت

اکنون یک پروژه جاوا از نوع [Java Application] برای بخش client برنامه ایجاد خواهیم کرد. تا ژوئن ۲۰۱۲، ایجاد یک پروژه Maven برای این مشتری امکان‌پذیر نبود. خطایی رخ می‌دهد که به نظر می‌رسد به خوبی به صورت آنلاین مستند شده است اما همچنان حل نشده باقی مانده است.

 

پس از ایجاد پروژه، مشخص می‌کنیم که این پروژه مشتری سرویس وبی خواهد بود که به تازگی روی سرور GlassFish مستقر کرده‌ایم:

  • در [2]، پروژه جدید را انتخاب کرده و دکمه [New File] را کلیک می‌کنیم
  • در [3]، مشخص می‌کنیم که می‌خواهیم یک کلاینت سرویس وب ایجاد کنیم
  • با استفاده از [4]، پروژه NetBeans را برای سرویس وب مشخص خواهیم کرد
  • در پنجره [5]، تمام پروژه‌هایی که دارای شاخه هستند فهرست شده‌اند؛ در [Web Services]، تنها پروژه [mv-pam-ws-metier-dao-eclipselink] نمایش داده می‌شود.
  • یک پروژه می‌تواند چندین سرویس وب را مستقر کند. در [6]، ما سرویس وبی را که می‌خواهیم به آن متصل شویم، مشخص می‌کنیم.
  • در [7]، URL که سرویس وب را تعریف می‌کند، نمایش داده می‌شود. این URL توسط ابزارهای نرم‌افزاری که لایه سمت کلاینت را تولید می‌کنند، استفاده می‌شود؛ لایه‌ای که با سرویس وب تعامل خواهد داشت.
  • لایه کلاینت [C] [1] که قرار است تولید شود، از مجموعه‌ای از کلاس‌های جاوا تشکیل شده است که در یک پکیج واحد قرار خواهند گرفت. نام این پکیج روی [8] تنظیم شده است.
  • پس از تکمیل جادوگر ایجاد کلاینت سرویس وب با کلیک بر روی دکمه [Finish]، لایه [C] که در بالا توصیف شد، ایجاد می‌شود.

این امر با چندین تغییر در پروژه منعکس می‌شود:

  • در [10] بالا، ساختار درختی [Generated Sources] ظاهر می‌شود که شامل کلاس‌های لایه [C] است که به کلاینت [3] امکان ارتباط با سرویس وب را می‌دهد. این لایه به کلاینت [3] امکان می‌دهد تا با لایه‌های [metier] و [4] چنان‌که محلی هستند و نه از راه دور، ارتباط برقرار کند.
  • در [11]، یک ساختار درختی ([Web Service References]) ظاهر می‌شود که وب‌سرویس‌هایی را فهرست می‌کند که برای آن‌ها یک لایه کلاینت تولید شده است.

شایان ذکر است که در لایه تولید شده [C] [10]، کلاس‌هایی را می‌یابیم که در سمت سرور مستقر شده‌اند: Indemnite, Cotisation, Employe, FeuilleSalaire, ElementsSalaire, Metier. Metier سرویس وب است و کلاس‌های دیگر، کلاس‌هایی هستند که توسط این سرویس مورد نیازند. ممکن است کسی کنجکاو باشد که کد آن‌ها را بررسی کند. خواهیم دید که تعریف کلاس‌ها — که هنگام نمونه‌سازی، اشیایی را که توسط سرویس دستکاری می‌شوند، نشان می‌دهند — شامل تعریف فیلدهای کلاس و دسترسی‌دهنده‌های آن‌ها، و همچنین افزودن آنوتیشن‌هایی است که به کلاس امکان سریالی‌سازی در یک جریان XML را می‌دهد. کلاس **Metier** به یک رابط تبدیل شده است که شامل دو متدی است که با @WebMethod نشانه‌گذاری شده‌اند. هر یک از این‌ها منجر به ایجاد دو کلاس می‌شود، برای مثال [CalculerFeuilleSalaire.java] و [CalculerFeuilleSalaireResponse.java]، که در آن یکی فراخوانی متد را در خود جای می‌دهد و دیگری نتیجه آن را. در نهایت، کلاس MetierService کلاسی است که به کلاینت اجازه می‌دهد مرجعی به سرویس وب کسب‌وکار راه دور به دست آورد:

1
2
3
4
    @WebEndpoint(name = "MetierPort")
    public Metier getMetierPort() {
        return super.getPort(new QName("http://metier/", "MetierPort"), Metier.class);
}

متد getMetierPort در خط ۲ برای به‌دست‌آوردن مرجع سرویس وب کسب‌وکار راه دور استفاده می‌شود.

8.1.2.2. کلاینت کنسولی برای سرویس وب تجاری

تنها کاری که باقی مانده، نوشتن کلاینت برای سرویس وب کسب‌وکار است. ما کلاس [MainRemote] را از پروژه [mv-pam-client-metier-dao-jpa-eclipselink] – که کلاینت سرور EJB بود – در پروژه جدید کپی می‌کنیم.

  • به [1]، کلاس کلاینت سرویس وب. کلاس [MainRemote] حاوی خطاهایی است. برای رفع این موارد، ابتدا تمام دستورات موجود [import] را از کلاس حذف کرده و سپس با استفاده از گزینه [Fix Imports] آن‌ها را مجدداً تولید می‌کنیم. این به این دلیل است که برخی از کلاس‌های مورد استفاده توسط کلاس [MainRemote] اکنون بخشی از بستهٔ تولیدشدهٔ [client] هستند.
  • در [3]، بخشی از کد که در آن لایه [metier] نمونه سازی می‌شود، [3] است. این کلاس با استفاده از کد JNDI ایجاد می‌شود تا مرجعی به یک EJB راه دور به دست آورد.

ما کد را به شرح زیر به‌روزرسانی می‌کنیم:

  • کد JNDI حذف می‌شود
  • از آنجا که کلاس [PamException] در سمت کلاینت وجود ندارد، ما catch مرتبط را حذف می‌کنیم تا تنها catch را روی کلاس والد [Exception] حفظ کنیم.
  • در [4]، ما همچنان باید یک مرجع به سرویس وب راه دور [Metier] به دست آوریم تا بتوانیم متد آن [calculerFeuilleSalaire] را فراخوانی کنیم.
  • در [5]، ما با استفاده از ماوس متد [calculerFeuilleSalaire] را از سرویس وب [Metier] می‌کشیم و در [4] رها می‌کنیم. کد [6] تولید می‌شود. این کد عمومی سپس می‌تواند توسط توسعه‌دهنده تطبیق داده شود.
  • در خط ۱۱۲، می‌بینیم که [calculerFeuilleSalaire] یک متد از کلاس [client.Metier] (خط ۱۱۱) است. اکنون که می‌دانیم چگونه لایه [metier] را به دست آوریم، کد قبلی را می‌توان به صورت زیر بازنویسی کرد:
...    
// مشکلی نیست – می‌توانیم فیش حقوقی را درخواست کنیم
    FeuilleSalaire feuilleSalaire = null;
    Metier metier = null;
    try {
       // مثال‌سازی لایه [metier]
      metier = new MetierService().getMetierPort();
       //محاسبه فیش حقوقی
      feuilleSalaire = metier.calculerFeuilleSalaire(args[0], nbHeuresTravaillées, nbJoursTravaillés);
    } catch (Throwable th) {
       // زنجیره استثنا
      System.out.println("Chaîne des exceptions --------------------------------------");
      System.out.println(th.getClass().getName() + ":" + th.getMessage());
      while (th.getCause() != null) {
        th = th.getCause();
        System.out.println(th.getClass().getName() + ":" + th.getMessage());
      }
      System.exit(1);
    }
     //نمایش سریع
...

خط ۷ یک مرجع به سرویس وب Metier را بازیابی می‌کند. پس از انجام این کار، کد کلاس بدون تغییر باقی می‌ماند، به جز اینکه در خط ۱۰، استثناء [Exception] نیست که مدیریت می‌شود، بلکه نوع عمومی‌تر Throwable مدیریت می‌شود، که کلاس والد کلاس Exception است. اگر خطایی رخ دهد، ما تمام علل تو در توی آن را تا ریشهٔ اصلی نمایش می‌دهیم.

ما برای تست آماده‌ایم:

  • اطمینان حاصل کنید که SGBD و MySQL5 راه‌اندازی شده‌اند و پایگاه داده dbpam_eclipselink ایجاد و اولیه شده است
  • اطمینان حاصل کنید که سرویس وب روی سرور GlassFish مستقر شده است
  • کلاینت را بسازید (پاک‌سازی و ساخت)
  • کلاینت را برای اجرا پیکربندی کنید
  
  • کلاینت را اجرا کنید

نتایج در کنسول به شرح زیر است:

...
Valeurs saisies :
N° de sécurité sociale de l'employé : 254104940426058
Nombre d'heures travaillées : 150
Nombre de jours travaillés : 20

Informations Employé : 
Nom : Jouveinal
Prénom : Marie
Adresse : 5 rue des oiseaux
...

با پیکربندی زیر:

Image

نتایج زیر به دست می‌آیند:

1
2
3
4
Chaîne des exceptions --------------------------------------
javax.xml.ws.soap.SOAPFaultException:L'employé de n°[xx] est introuvable
com.sun.xml.internal.ws.developer.ServerSideException:L'employé de n°[xx] est introuvable
Java Result: 1

شایان ذکر است که در حالی که سرویس وب [Metier] یک استثنا از نوع [PamException] ارسال می‌کند، استثنای دریافتی توسط کلاینت از نوع [SOAPFaultException] است. حتی در زنجیره استثناء، نوع [PamException] ظاهر نمی‌شود.

8.1.3. کلاینت Swing برای سرویس وب Metier


وظیفه: انتقال کلاینت Swing از پروژه [mv-pam-client-ejb-metier-dao-jpa-eclipselink] به پروژه جدید، به گونه‌ای که آن نیز به کلاینت سرویس وب مستقر شده بر روی سرور GlassFish تبدیل شود.


8.2. سرویس وب پیاده‌سازی‌شده توسط یک برنامه وب

اکنون چارچوب معماری زیر را در نظر می‌گیریم:

سرویس وب توسط یک برنامه وب که درون محفظه وب سرور GlassFish اجرا می‌شود، ارائه می‌گردد. این سرویس وب بر روی کامپوننت‌های EJB و [Metier] که خود در محفظه EJB3 مستقر شده‌اند، متکی است.

8.2.1. سوی سرور

ما یک برنامه وب ایجاد می‌کنیم:

  • در [1]، یک پروژه جدید ایجاد می‌کنیم
  • در [2]؛ این پروژه از نوع [Web Application] است
  • در [3]، آن را [mv-pam-ws-ejb-metier-dao-eclipselink] نام‌گذاری می‌کنیم
  • در [4]، نسخهٔ ۶ Java EE را انتخاب می‌کنیم
  • در [6]، پروژه ایجاد شده

در نمودار زیر، اپلیکیشن وب ایجادشده در کانتینر وب اجرا خواهد شد. این اپلیکیشن از EJB و [Metier] استفاده می‌کند که به نوبه خود در کانتینر EJB سرور مستقر خواهند شد.

برای اطمینان از اینکه برنامه وب ایجاد شده به کلاس‌های مرتبط با EJB و [Metier] دسترسی دارد، ما [mv-pam-ws-ejb-metier-dao-eclipselink] را به کتابخانه‌های برنامه وب اضافه می‌کنیم، وابستگی سرور EJB [mv-pam-ejb-metier-dao-eclipselink]، که قبلاً در مورد آن بحث کرده‌ایم.

  • در [1]، یک پروژه را به وابستگی‌های پروژه وب اضافه می‌کنیم،
  • در [2]، پروژه [mv-pam-ejb-metier-dao-eclipselink] انتخاب می‌شود،
  • در [3]، نوع وابستگی ejb است،
  • در [4]، دامنه وابستگی provided است، یعنی این وابستگی توسط محیط زمان اجرا فراهم خواهد شد،
  • در [5]، وابستگی اضافه شده است.

برای ایجاد همان سرویس وب مانند قبل، باید:

  • ایجاد یک کلاس با تگ @Webservice
  • با دو متد calculerFeuilleSalaire و findAllEmployes که با @WebMethod تگ شده‌اند

ما یک کلاس به نام [PamWsEjbMetier] را در داخل یک پکیج به نام [pam.ws] ایجاد می‌کنیم:

  

کلاس [PamWsEjbMetier] به شرح زیر است:

package pam.ws;

import java.util.List;
import javax.ejb.EJB;
import javax.jws.WebMethod;
import javax.jws.WebService;
import jpa.Employe;
import metier.FeuilleSalaire;
import metier.IMetier;
import metier.IMetierLocal;

@WebService
public class PamWsEjbMetier implements IMetier{

  @EJB
  private IMetierLocal metier;

  @WebMethod
  public FeuilleSalaire calculerFeuilleSalaire(String SS, double nbHeuresTravaillées, int nbJoursTravaillés) {
    return metier.calculerFeuilleSalaire(SS, nbHeuresTravaillées, nbJoursTravaillés);
  }

  @WebMethod
  public List<Employe> findAllEmployes() {
    return metier.findAllEmployes();
  }

}
  • خطوط ۷–۱۰: کلاس، کلاس‌هایی را از ماژول‌های EJB و [pam-serveurws-metier-dao-jpa-eclipselink] وارد می‌کند که پروژه‌های Maven آن‌ها به وابستگی‌های پروژه اضافه شده‌اند.
  • خط ۱۲: این کلاس یک سرویس وب است
  • خط ۱۳: این کلاس رابط IMetier را که در ماژول EJB تعریف شده است، پیاده‌سازی می‌کند
  • خطوط ۱۸–۱۹: متد calculerFeuilleSalaire به‌عنوان یک متد سرویس وب ارائه شده است
  • خطوط ۲۳–۲۴: متد findAllEmployes به عنوان یک متد سرویس وب ارائه شده است
  • خطوط ۱۵–۱۶: رابط محلی EJB [Metier] در فیلد در خط ۱۶ تزریق می‌شود. ما از رابط محلی استفاده می‌کنیم زیرا وب‌اپلیکیشن و ماژول EJB در همان JVM اجرا می‌شوند.
  • خطوط ۲۰ و ۲۵: متدهای calculerFeuilleSalaire و findAllEmployes پردازش خود را به متدهای هم‌نام در کلاس EJB [Metier] واگذار می‌کنند. بنابراین این کلاس تنها برای در دسترس قرار دادن متدهای EJB و [Metier] به کلاینت‌های راه دور به عنوان متدهای سرویس وب عمل می‌کند.

در NetBeans، اپلیکیشن وب به‌عنوان ارائه‌دهنده یک سرویس وب شناسایی می‌شود:

برای استقرار سرویس وب بر روی سرور GlassFish، ما باید هر دو را مستقر کنیم:

  • ماژول وب در کانتینر وب سرور
  • ماژول EJB را در کانtejner EJB سرور

برای این کار، باید یک برنامه از نوع [Enterprise Application] ایجاد کنیم که هر دو ماژول را همزمان مستقر کند. برای این کار، هر دو پروژه باید در NetBeans [2] بارگذاری شوند.

پس از انجام این کار، یک پروژه جدید [3] ایجاد می‌کنیم.

  • در [4]، نوع پروژه را [Enterprise Application] انتخاب می‌کنیم.
  • در [5]، پروژه را نام‌گذاری می‌کنیم
  • در [6]، پروژه را پیکربندی می‌کنیم. نسخهٔ جاوا برای EE، جاوا EE 6 خواهد بود. یک پروژهٔ سازمانی می‌تواند با دو ماژول ایجاد شود: یک ماژول EJB و یک ماژول وب. در اینجا، پروژهٔ سازمانی، ماژول وب و ماژول EJB را که قبلاً ایجاد و در NetBeans بارگذاری شده‌اند، در بر می‌گیرد. بنابراین، ما درخواست ایجاد هیچ ماژول جدیدی را نداریم.
  • در [7]، پروژهٔ سازمانی [mv-pam-webapp-ear] همان‌طور که توضیح داده شد ایجاد می‌شود. یک پروژهٔ Maven دیگر، [mv-pam-webapp]، همزمان ایجاد شد. ما با این پروژه سر و کار نخواهیم داشت.
  • در [8]، ما وابستگی‌ها را به پروژه سازمانی اضافه می‌کنیم
  • در [9]، پروژه وب از نوع WAR را اضافه می‌کنیم،
  • در [10]، پروژه نوع EJB EJB را اضافه می‌کنیم،
  • در [11]، پروژه سازمانی به همراه دو وابستگی آن.

ما پروژهٔ سازمانی را با استفاده از «پاک‌سازی و ساخت» (Clean and Build) می‌سازیم. تقریباً آمادهٔ استقرار آن روی سرور GlassFish هستیم. پیش از انجام این کار، ممکن است لازم باشد هر برنامه‌ای را که قبلاً روی سرور بارگذاری شده است تخلیه کنید تا از تداخل نام احتمالی بین EJB و [11] جلوگیری شود:

سرور MySQL باید در حال اجرا باشد و پایگاه داده [dbpam_eclipselink] باید موجود و حاوی داده‌ها باشد. پس از انجام این کار، می‌توان برنامه سازمانی را به عنوان [12] مستقر کرد. در [13]، می‌توانید ببینید که در واقع بر روی سرور GlassFish مستقر شده است.

ما می‌توانیم سرویس وبی را که به‌تازگی مستقر شده است، آزمایش کنیم:

  • در [1]، ما درخواست می‌کنیم سرویس وب [PamWsEjbMetier] را آزمایش کنیم
  • به [2]، صفحهٔ تست. انجام تست‌ها را به خواننده واگذار می‌کنیم.

8.2.2. سمت کلاینت


وظیفه: با دنبال کردن رویه‌ای که در بخش 8.1.2.1 شرح داده شده است، یک کلاینت کنسولی برای سرویس وب قبلی بسازید.


8.3. سرویس وب با Spring و Tomcat پیاده‌سازی شده است

اکنون معماری زیر را در نظر می‌گیریم:

سرویس وب توسط یک برنامه وب که در داخل محفظه وب سرور Tomcat اجرا می‌شود، ارائه می‌شود. معماری برنامه به شرح زیر خواهد بود:

ما بر روی پروژه [mv-pam-spring-hibernate] که در بخش 5.11 ایجاد شده است، کار خواهیم کرد:

  

8.3.1. سویٔل سرور

ما یک برنامه وب Maven به نام [mv-pam-ws-spring-tomcat] [1] ایجاد می‌کنیم:

ما فایل [pom.xml] را برای شامل کردن وابستگی‌های زیر اصلاح می‌کنیم:


  <dependencies>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>mv-pam-spring-hibernate</artifactId>
      <version>${project.version}</version>
    </dependency>
    <!--وابستگی‌های Apache CXF -->
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-frontend-jaxws</artifactId>
      <version>2.2.12</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http</artifactId>
      <version>2.2.12</version>
    </dependency>
</dependencies>
  • خطوط ۳–۷: وابستگی به پروژه [spring-pam-jpa-hibernate
  • خطوط ۸–۱۷: وابستگی‌ها به فریم‌ورک آپاچی CXF و [http://cxf.apache.org/]. این فریم‌ورک ایجاد سرویس‌های وب را تسهیل می‌کند.

این فایل، [pom.xml]، وابستگی‌های متعددی را معرفی می‌کند، [2].

بیایید به معماری برنامه بازگردیم:

فراخوانی‌های سرویس وبی که قصد ساخت آن را داریم توسط یک سرولت از فریم‌ورک CXF مدیریت می‌شوند. این موضوع در فایل [WEB-INF / web.xml] به شرح زیر منعکس شده است:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name>mv-pam-ws-spring-tomcat</display-name>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
<!--  پیکربندی CXF -->
  <servlet>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
    <url-pattern>/ws/*</url-pattern>
  </servlet-mapping>
  <session-config>
    <session-timeout>
      30
    </session-timeout>
  </session-config>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
  • چارچوب CXF به Spring وابسته است. خطوط ۴–۶: یک listener اعلام می‌شود. کلاس متناظر همزمان با بارگذاری برنامه وب بارگذاری خواهد شد. این کلاس از فایل پیکربندی Spring به آدرس [WEB-INF / applicationContext.xml] استفاده می‌کند:
  • خطوط ۸–۱۲: سرولتی به نام CXF که درخواست‌های مربوط به سرویس وبی را که قصد داریم ایجاد کنیم، مدیریت خواهد کرد،
  • خطوط ۱۳–۱۶: درخواست‌های با شکل /ws/* توسط servlet CXF پردازش خواهند شد. سایر موارد توسط CXF پردازش نخواهند شد.

برای تعریف سرویس وب، یک رابط و پیاده‌سازی آن را تعریف می‌کنیم:

رابط [IWsMetier] به شرح زیر خواهد بود:


package pam.ws;

import javax.jws.WebService;
import metier.IMetier;

@WebService
public interface IWsMetier extends IMetier{
  
}
  • خط ۷: رابط [IWsMetier] از رابط [IMetier] در لایه [métier] پروژه [mv-pam-spring-hibernate]، مشتق می‌شود،
  • خط ۶: رابط [IWsMetier] یک سرویس وب است.

کلاس پیاده‌سازی این رابط به شرح زیر است:


package pam.ws;

import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
import jpa.Employe;
import metier.FeuilleSalaire;
import metier.IMetier;

@WebService
public class PamWsMetier implements IWsMetier {

  //لایه کسب‌وکار
  private IMetier metier;
  
  // سازنده
  public PamWsMetier(){
    
  }
  
  @WebMethod
  public FeuilleSalaire calculerFeuilleSalaire(String SS, double nbHeuresTravaillees, int nbJoursTravailles) {
    return metier.calculerFeuilleSalaire(SS, nbHeuresTravaillees, nbJoursTravailles);
  }

  @WebMethod
  public List<Employe> findAllEmployes() {
    return metier.findAllEmployes();
  }
  
  // گیرنده و تنظیم‌کننده

  public void setMetier(IMetier metier) {
    this.metier = metier;
  }
  
}
  • خط ۱۱: کلاس [PamWsMetier] رابط تعریف‌شده در بالا را پیاده‌سازی می‌کند،
  • خط ۱۰: کلاس را به‌عنوان یک سرویس وب تعریف می‌کند،
  • خط ۱۴: لایه [métier] توسط Spring تزریق خواهد شد،
  • خطوط ۲۱ و ۲۶: آناوتیشن @WebMethod یک متد را به عنوان متدی که توسط سرویس وب ارائه می‌شود، مشخص می‌کند،
  • خطوط ۲۳ و ۲۸: متدها با استفاده از لایه [métier] پیاده‌سازی شده‌اند.

اکنون باید محتویات فایل پیکربندی Spring با نام [applicationContext.xml] را تعریف کنیم:

محتویات آن به شرح زیر است:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://cxf.apache.org/jaxws
       http://cxf.apache.org/schemas/jaxws.xsd">
  
  <!-- آپاچی CXF -->
  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  

  <!-- لایه‌های پایین‌تر -->
  <import resource="classpath:spring-config-metier-dao.xml" />  
  
  <!-- سرویس وب -->
  <bean id="wsMetier" class="pam.ws.PamWsMetier">
    <property name="metier" ref="metier"/>
  </bean>
  <jaxws:endpoint id="wsmetier"
                  implementor="#wsMetier"
                  address="/metier">
  </jaxws:endpoint>  

</beans>
  • خطوط ۱۳–۱۵: فایل‌های پیکربندی آپاچی CXF وارد می‌شوند. این فایل‌ها در Classpath پروژه (ویژگی classpath) جستجو می‌شوند،
  • خطوط ۴، ۹، ۱۰: فضاهای نام مخصوص آپاچی CXF اعلام می‌شوند،
  • خط ۱۸: فایل پیکربندی Spring از پروژه [mv-pam-spring-hibernate] وارد می‌شود،
  • خطوط 21–23: تعریف کردن بیون سرویس وب با وابستگی آن به لایه [métier] (خط 22)،
  • خطوط ۲۴–۲۷: خود سرویس وب را تعریف می‌کنند،
    • خط ۲۵: بین (Bean) اسپرینگ که وب سرویس را پیاده‌سازی می‌کند، همان است که در خط ۲۱ تعریف شده است؛
    • خط ۲۶: مسیری را که سرویس وب تحت آن در دسترس خواهد بود تعریف می‌کند، در این مورد /metier. با ترکیب با فرمت مورد نیاز برای URLهایی که توسط آپاچی پردازش می‌شوند (به فایل web.xml مراجعه کنید)، این URL به /ws/metier تبدیل می‌شود.

پروژه ما آماده اجرا است. ما آن را اجرا می‌کنیم و در یک مرورگر URL و [http://localhost:8080/mv-pam-ws-spring-tomcat/ws] را درخواست می‌کنیم:

Image

صفحه تمام سرویس‌های وب راه‌اندازی‌شده را فهرست می‌کند. در این مورد، تنها یک سرویس وجود دارد. ما لینک WSDL را دنبال می‌کنیم:

متن نمایش داده شده، [1]، از فایلی به نام XML گرفته شده است که عملکرد سرویس وب، نحوه فراخوانی آن و پاسخ‌هایی را که بازمی‌گرداند، تعریف می‌کند. توجه کنید که در این فایل، WSDL، به URL و [2] اشاره شده است. همهٔ کلاینت‌های سرویس وب باید این موضوع را بدانند.

8.3.2. طرف مشتری


وظیفه: با دنبال کردن رویه‌ای که در بخش 8.1.2.1 توضیح داده شده است، یک کلاینت کنسولی برای سرویس وب فوق‌الذکر بسازید.


توجه: برای مشخص کردن URL از فایل WSDL سرویس وب، مراحل زیر را دنبال کنید:

[3] را روی مقداری که قبلاً در [2] به عنوان URL ثبت شده بود، تنظیم کنید.