16. مقدمة إلى Spring MVC
16.1. دور Spring MVC في تطبيق ويب
لنحدد مكانة Spring MVC في تطوير تطبيق ويب. في أغلب الأحيان، سيتم بناء هذا التطبيق على بنية متعددة الطبقات مثل التالية:
![]() |
- الطبقة [Web] هي الطبقة التي تتفاعل مع مستخدم تطبيق الويب. يتفاعل المستخدم مع تطبيق الويب من خلال صفحات الويب التي يتم عرضها بواسطة متصفح. يقع Spring MVC في هذه الطبقة وحسب؛
- تقوم الطبقة [métier] بتنفيذ قواعد إدارة التطبيق، مثل حساب الراتب أو الفاتورة. تستخدم هذه الطبقة البيانات الواردة من المستخدم عبر الطبقة [Web] ومن SGBD عبر الطبقة [DAO]؛
- تتولى الطبقة [DAO] (كائنات الوصول إلى البيانات)، والطبقة [ORM] (أداة التعيين العلائقي للكائنات)، وبرنامج التشغيل JDBC إدارة الوصول إلى بيانات الطبقة SGBD. تشكل الطبقة [ORM] جسرًا بين الكائنات التي تتعامل معها الطبقة [DAO] والصفوف والأعمدة في جداول قاعدة البيانات العلائقية. تسمح مواصفة تُعرف باسم JPA (Java Persistence API) بالتجريد من ORM المستخدم إذا كان هذا الأخير يطبق هذه المواصفات. سيكون هذا هو الحال في هذا الدرس التعليمي، ولذلك سنطلق من الآن فصاعدًا على الطبقة ORM اسم الطبقة JPA؛
- ويتم تكامل الطبقات بواسطة إطار عمل Spring؛
16.2. نموذج تطوير Spring MVC
يقوم Spring MVC بتنفيذ نموذج الهندسة المعمارية المعروف باسم MVC (النموذج – العرض – وحدة التحكم) بالطريقة التالية:
![]() |
تتم معالجة طلب العميل على النحو التالي:
- الطلب - تكون URL المطلوبة على شكل http://machine:port/contexte/Action/param1/param2/....?p1=v1&p2=v2&... يستخدم [Front Controller] ملف تكوين أو تعليقات توضيحية في Java لتوجيه الطلب إلى وحدة التحكم الصحيحة والإجراء الصحيح داخل تلك الوحدة. ولذلك، يستخدم الحقل [Action] الموجود في URL. أما باقي أجزاء URL و[/param1/param2/...] فهي تتكون من معلمات اختيارية سيتم تمريرها إلى الإجراء. الحرف C في MVC هو هنا السلسلة [Front Controller, Contrôleur, Action]. إذا لم يتمكن أي وحدة تحكم من معالجة الإجراء المطلوب، فسيرد خادم الويب بأن URL المطلوب لم يتم العثور عليه.
- المعالجة
- (تابع)
- يمكن للإجراء المختار الاستفادة من المعلمات parami التي أرسلها إليه [Front Controller]. وقد تأتي هذه المعلمات من عدة مصادر:
- مسار [/param1/param2/...] الخاص بـ URL،
- من المعلمات [p1=v1&p2=v2] الخاصة بـ URL,
- من المعلمات التي يرسلها المتصفح مع طلبه؛
- أثناء معالجة طلب المستخدم، قد تحتاج العملية إلى الطبقة [métier] و [2b]. بمجرد معالجة طلب العميل، قد يؤدي ذلك إلى استدعاء استجابات متنوعة. ومن الأمثلة النموذجية على ذلك:
- صفحة خطأ إذا تعذر معالجة الطلب بشكل صحيح
- صفحة تأكيد في الحالات الأخرى
- تطلب الإجراء عرض طريقة عرض معينة [3]. ستعرض طريقة العرض هذه البيانات التي نسميها نموذج طريقة العرض. وهذا هو الحرف M في MVC. ستقوم الإجراء بإنشاء هذا النموذج M [2c] وستطلب عرض طريقة عرض V [3]؛
- الاستجابة - تستخدم طريقة العرض V المختارة النموذج M الذي أنشأته العملية لتهيئة الأجزاء الديناميكية من الاستجابة HTML التي يجب أن ترسلها إلى العميل، ثم ترسل هذه الاستجابة.
بالنسبة لخدمة ويب / jSON، يتم تعديل البنية السابقة بشكل طفيف:
![]() |
- في [4a]، يتم تحويل النموذج — وهو فئة Java — إلى سلسلة jSON بواسطة مكتبة jSON؛
- في [4b]، يتم إرسال هذه السلسلة jSON إلى المتصفح؛
الآن، دعونا نوضح العلاقة بين بنية الويب MVC وبنية الطبقات. وفقًا للتعريف الذي نعطيه للنموذج، قد يكون هذان المفهومان مرتبطين أو غير مرتبطين. لنأخذ تطبيق ويب Spring أحادي الطبقة MVC كمثال:
![]() |
إذا قمنا بتنفيذ الطبقة [Web] باستخدام Spring MVC، فسنحصل بالفعل على بنية ويب MVC ولكنها لن تكون بنية متعددة الطبقات. هنا، ستتولى الطبقة [web] كل شيء: العرض، والعمليات التجارية، والوصول إلى البيانات. وستقوم الإجراءات (Actions) بهذه المهام.
الآن، لننظر إلى بنية ويب متعددة الطبقات:
![]() |
يمكن تنفيذ الطبقة [Web] بدون إطار عمل وبدون اتباع النموذج MVC. وبذلك يكون لدينا بالفعل بنية متعددة الطبقات، لكن الطبقة الويب لا تنفذ النموذج MVC.
على سبيل المثال، في عالم .NET، يمكن تنفيذ الطبقة [Web] المذكورةأعلاه يمكن تنفيذها باستخدام ASP.NET و MVC، وبذلك نحصل على بنية طبقات تحتوي على طبقة [Web] من النوع MVC. وبعد ذلك، يمكن استبدال هذه الطبقة ASP.NET وMVC بطبقة ASP.NET تقليدية (WebForms) مع الحفاظ على بقية (المجال، DAO، ORM) كما هو. وبذلك نحصل على بنية طبقية تحتوي على طبقة [Web] التي لم تعد من النوع MVC.
في MVC، ذكرنا أن النموذج M هو نموذج العرض V، c.a.d، أي مجموعة البيانات المعروضة بواسطة العرض V. وهناك تعريف آخر للنموذج M الخاص بـ MVC، وهو:
![]() |
يعتبر العديد من المؤلفين أن ما يقع على يمين الطبقة [Web] يشكل النموذج M لـ MVC. لتجنب الغموض، يمكننا التحدث عن:
- عن «نموذج المجال» عند الإشارة إلى كل ما يقع على يمين الطبقة [Web]
- عن «نموذج العرض» عند الإشارة إلى البيانات المعروضة بواسطة عرض V
وفيما يلي، سيشير مصطلح «نموذج M» حصريًّا إلى نموذج العرض V.
16.3. مشروع ويب / jSON باستخدام Spring MVC
يقدم موقع [http://spring.io/guides] دروسًا تعليمية للمبتدئين لاكتشاف نظام Spring. سنتبع إحدى هذه الدروس لاكتشاف إعدادات Maven اللازمة لمشروع Spring MVC.
16.3.1. مشروع العرض التوضيحي
![]() |
- في [1]، نقوم باستيراد أحد أدلة Spring؛
![]() |
- في [2]، نختار المثال [Rest Service]؛
- في [3]، نختار مشروع Maven؛
- في [4]، نأخذ النسخة النهائية من الدليل؛
- في [5]، نقوم بالتحقق من الصحة؛
- في [6]، المشروع المستورد؛
غالبًا ما تُسمى الخدمات الويب التي يمكن الوصول إليها عبر معايير URL والتي تقدم نصًا jSON بخدمات REST (REpresentational State Transfer). تُسمى الخدمة «Restful» إذا كانت تلتزم بقواعد معينة.
لنلقِ نظرة الآن على المشروع المستورد، بدءًا من تكوين Maven الخاص به.
16.3.2. تكوين Maven
ملف [pom.xml] هو كما يلي:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<properties>
<start-class>hello.Application</start-class>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>
- الأسطر 6-8: خصائص مشروع Maven. ينقص علامة [<packaging>] التي تشير إلى نوع الملف الناتج عن تجميع Maven. وفي حالة عدم وجودها، يتم استخدام النوع [jar]. وبالتالي، فإن التطبيق هو تطبيق قابل للتنفيذ من نوع وحدة التحكم، وليس تطبيق ويب حيث يكون التعبئة عندئذٍ [war]؛
- الأسطر 10-14: يحتوي مشروع Maven على مشروع أبوي [spring-boot-starter-parent]. وهو الذي يحدد الجزء الأكبر من تبعيات المشروع. قد تكون هذه التبعيات كافية، وفي هذه الحالة لا يتم إضافة المزيد، أو قد لا تكون كافية، وفي هذه الحالة يتم إضافة التبعيات الناقصة؛
- الأسطر 17-20: يجلب الأرتيفاكت [spring-boot-starter-web] معه المكتبات اللازمة لمشروع Spring MVC من نوع خدمة الويب حيث لا توجد عروض مُنشأة. يحتوي هذا الأرتيفاكت على عدد كبير جدًا من المكتبات، بما في ذلك مكتبات خادم Tomcat المدمج. وسيتم تشغيل التطبيق على هذا الخادم؛
المكتبات التي توفرها هذه التهيئة عديدة جدًّا:
![]() | ![]() |
في الأعلى، نرى الأرشيفات الثلاثة لخادم Tomcat.
16.3.3. بنية خدمة Spring [web / jSON]
بالنسبة لخدمة ويب / jSON، يقوم Spring MVC بتنفيذ النموذج MVC بالطريقة التالية:
![]() |
- في [4a]، يتم تحويل النموذج، وهو فئة Java، إلى سلسلة jSON بواسطة مكتبة jSON؛
- في [4b]، يتم إرسال هذه السلسلة jSON إلى المتصفح؛
16.3.4. وحدة التحكم C
![]() |
يحتوي التطبيق المستورد على وحدة التحكم التالية:
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
- السطر 9: التعليق التوضيحي [@RestController] يجعل من الفئة [GreetingController] وحدة تحكم Spring، أي أن أساليبها مسجلة لمعالجة URL. لقد رأينا التعليق التوضيحي المماثل [@Controller]. وكانت نتيجة أساليب هذا المُتحكم من النوع [String]، وهو اسم العرض المطلوب عرضه. الأمر مختلف هنا. تُرجع أساليب وحدة التحكم من النوع [@RestController] كائنات يتم تسلسلها لإرسالها إلى المتصفح. يعتمد نوع التسلسل الذي يتم إجراؤه على تكوين Spring MVC. هنا، سيتم تسلسلها إلى jSON. إن وجود مكتبة jSON ضمن تبعيات المشروع هو ما يجعل Spring Boot يقوم، عن طريق التكوين التلقائي، بتكوين المشروع بهذه الطريقة؛
- السطر 14: تشير العلامة التوضيحية [@RequestMapping] إلى URL الذي تعالجه الطريقة، وهو هنا URL [/greeting]؛
- السطر 15: سبق أن شرحنا التعليق التوضيحي [@RequestParam]. والنتيجة التي تُرجعها الطريقة هي كائن من النوع [Greeting].
- السطر 12: عدد صحيح طويل من النوع الذري. وهذا يعني أنه يدعم التنافس في الوصول. قد ترغب عدة خيوط في زيادة قيمة المتغير [counter] في نفس الوقت. وسيتم ذلك بشكل سليم. لا يمكن لأي خيط قراءة قيمة العداد إلا إذا كان الخيط الذي يقوم بتعديله قد أنهى تعديله.
16.3.5. النموذج M
النموذج M الناتج عن الطريقة السابقة هو الكائن [Greeting] التالي:
![]() |
package hello;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
سيؤدي تحويل هذا الكائن باستخدام jSON إلى إنشاء السلسلة {"id":n,"content":"نص"}. وفي النهاية، ستكون السلسلة jSON الناتجة عن طريقة وحدة التحكم على النحو التالي:
أو
16.3.6. التنفيذ
![]() |
الفئة [Application.java] هي الفئة القابلة للتنفيذ في المشروع. وفيما يلي شفرتها:
package hello;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
لقد سبق أن تناولنا هذا الكود وشرحناه في المثال السابق. لنقم بتشغيل المشروع:
![]() |
نحصل على سجلات وحدة التحكم التالية:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.1.9.RELEASE)
2014-11-28 15:22:55.005 INFO 3152 --- [ main] hello.Application : Starting Application on Gportpers3 with PID 3152 (started by ST in D:\data\istia-1415\spring mvc\dvp-final\gs-rest-service)
2014-11-28 15:22:55.046 INFO 3152 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@62e136d3: startup date [Fri Nov 28 15:22:55 CET 2014]; root of context hierarchy
2014-11-28 15:22:55.762 INFO 3152 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2014-11-28 15:22:56.567 INFO 3152 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8080
2014-11-28 15:22:56.738 INFO 3152 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat
2014-11-28 15:22:56.740 INFO 3152 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.56
2014-11-28 15:22:56.869 INFO 3152 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2014-11-28 15:22:56.870 INFO 3152 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1827 ms
2014-11-28 15:22:57.478 INFO 3152 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2014-11-28 15:22:57.481 INFO 3152 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2014-11-28 15:22:57.685 INFO 3152 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-11-28 15:22:57.879 INFO 3152 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/greeting],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public hello.Greeting hello.GreetingController.greeting(java.lang.String)
2014-11-28 15:22:57.884 INFO 3152 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2014-11-28 15:22:57.885 INFO 3152 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[text/html],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2014-11-28 15:22:57.906 INFO 3152 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] إلى معالج من النوع [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-11-28 15:22:57.907 INFO 3152 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] معالج من النوع [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-11-28 15:22:58.231 INFO 3152 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2014-11-28 15:22:58.318 INFO 3152 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080/http
2014-11-28 15:22:58.319 INFO 3152 --- [ main] hello.Application : Started Application in 3.788 seconds (JVM running for 4.424)
- السطر 13: يتم تشغيل خادم Tomcat على المنفذ 8080 (السطر 12)؛
- السطر 17: السيرفلت [DispatcherServlet] موجود؛
- السطر 20: تم اكتشاف الطريقة [GreetingController.greeting]؛
لاختبار تطبيق الويب، نطلب URL [http://localhost:8080/greeting]:
![]() | ![]() |
ونستقبل بالفعل السلسلة المتوقعة jSON. قد يكون من المثير للاهتمام الاطلاع على الرؤوس HTTP المرسلة من الخادم. ولذلك، سنستخدم ملحق Chrome المسمى [Advanced Rest Client] (Chrome / Ctrl-T / قائمة [Applications] / [Advanced Rest Client] - انظر المرفقات، الفقرة 23.11):
![]() |
- في [1]، يتم طلب URL؛
- في [2]، تُستخدم الطريقة GET؛
- في [3]، الرد jSON؛
- في [4]، أشار الخادم إلى أنه يرسل استجابة بتنسيق jSON؛
- في [5]، يُطلب نفس URL ولكن هذه المرة مع POST؛
- في [7]، يتم إرسال المعلومات إلى الخادم في شكل [urlencoded]؛
- في [6]، المعلمة name مع قيمتها؛
- في [8]، يُعلم المتصفح الخادم بأنه يرسل إليه معلومات [urlencoded]؛
- في [9]، الرد jSON من الخادم؛
16.3.7. إنشاء أرشيف قابل للتنفيذ
نقوم الآن بإنشاء ملف مضغوط قابل للتنفيذ:
![]() |
![]() |
- في [1]: يتم تنفيذ هدف Maven؛
- في [2]: يوجد هدفان (goals): [clean] لحذف المجلد [target] من مشروع Maven، و[package] لإعادة إنشائه؛
- في [3]: سيتم إنشاء المجلد [target] في هذا المجلد؛
- في [4]: يتم إنشاء الهدف؛
في السجلات التي تظهر في وحدة التحكم، من المهم أن يظهر المكون الإضافي [spring-boot-maven-plugin]. فهو الذي يقوم بإنشاء الأرشيف القابل للتنفيذ (انظر [pom.xml] أدناه):
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
باستخدام وحدة التحكم، ننتقل إلى المجلد الذي تم إنشاؤه:
D:\Temp\wksSTS\gs-rest-service\target>dir
...
11/06/2014 15:30 <DIR> classes
11/06/2014 15:30 <DIR> generated-sources
11/06/2014 15:30 11 073 572 gs-rest-service-0.1.0.jar
11/06/2014 15:30 3 690 gs-rest-service-0.1.0.jar.original
11/06/2014 15:30 <DIR> maven-archiver
11/06/2014 15:30 <DIR> maven-status
...
- السطر 5: الملف المضغوط الذي تم إنشاؤه؛
يتم تشغيل هذه الملف المضغوط بالطريقة التالية:
D:\Temp\wksSTS\gs-rest-service-complete\target>java -jar gs-rest-service-0.1.0.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.1.0.RELEASE)
2014-06-11 15:32:47.088 INFO 4972 --- [ main] hello.Application
: Starting Application on Gportpers3 with PID 4972 (D:\Temp\wk
sSTS\gs-rest-service-complete\target\gs-rest-service-0.1.0.jar started by ST in
D:\Temp\wksSTS\gs-rest-service-complete\target)
...
الآن بعد تشغيل تطبيق الويب، يمكن الوصول إليه باستخدام متصفح:
![]() |
16.3.8. نشر التطبيق على خادم Tomcat
كما فعلنا في المشروع السابق، نقوم بتعديل الملف [pom.xml] بالطريقة التالية:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.1.0</version>
<packaging>war</packaging>
...
</project>
- السطر 9: يجب الإشارة إلى أننا سنقوم بإنشاء أرشيف war (Web ARchive)؛
كما يجب تكوين تطبيق الويب. وفي حالة عدم وجود ملف [web.xml]، يتم ذلك باستخدام فئة ترث من [SpringBootServletInitializer]:
![]() |
الفئة [ApplicationInitializer] هي كما يلي:
package hello;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
public class ApplicationInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
- السطر 6: الفئة [ApplicationInitializer] تمتد من الفئة [SpringBootServletInitializer]؛
- السطر 9: تم إعادة تعريف الطريقة [configure] (السطر 8)؛
- السطر 10: يتم توفير الفئة التي تهيئ المشروع؛
لتنفيذ المشروع، يمكن اتباع الخطوات التالية:
![]() |
- في [1-2]، يتم تنفيذ المشروع على أحد الخوادم المسجلة في IDE Eclipse؛
وبعد ذلك، يمكن طلب URL [http://localhost:8080/gs-rest-service/greeting/?name=Mitchell] في متصفح:
![]() |
16.4. الخلاصة
لقد قدمنا نوعًا من مشاريع Spring MVC حيث ترسل تطبيق الويب دفقًا jSON إلى المتصفح. سنقوم الآن بتطوير تطبيق ويب / jSON لعرض قاعدة البيانات [dbproduitscategories] التي تمت دراستها في الفصول السابقة على الويب.























