أساسيات Spring Boot

إنشاء مشروع Spring Boot

18 دقيقة الدرس 2 من 13

إنشاء مشروع Spring Boot

كل تطبيق Spring Boot ينطلق من ثلاثة عناصر: هيكل مشروع مُوَلَّد عبر Spring Initializr، وتخطيط دليل محدد بدقة، وفئة رئيسية وحيدة تحمل التعليقات التوضيحية المطلوبة وتعمل على تمهيد الإطار بأكمله. يُشرّح هذا الدرس العناصر الثلاثة، لتفهم ليس فقط ما يوجد، بل لماذا يوجد وما الذي يمكنك تعديله بأمان.

Spring Initializr — مولّد المشاريع

start.spring.io هو مولّد المشاريع الرسمي المستند إلى المتصفح والذي يُشرف عليه فريق Spring. يُنتج أرشيف مشروع جاهز للاستيراد في ثوانٍ. يتوفر الجيل نفسه داخل IntelliJ IDEA (File → New → Project → Spring Initializr) وفي VS Code عبر حزمة Spring Boot Extension Pack. كلا الخيارين يستدعيان واجهة REST نفسها في الخلفية.

الخيارات الأساسية التي تحددها في النموذج:

  • نوع المشروع: Maven أو Gradle (بـ DSL بصيغة Groovy أو Kotlin). Maven هو الخيار الأكثر أمانًا للفرق؛ أما Gradle فأسرع في بناء المشاريع الكبيرة.
  • اللغة: Java (هذا الكورس)، أو Kotlin، أو Groovy.
  • إصدار Spring Boot: اختر دائمًا أحدث إصدار GA (متاح للعموم). في Spring Boot 3.x، الحد الأدنى لإصدار Java هو 17.
  • Group / Artifact / Name / Description: إحداثيات Maven القياسية. استخدم مجموعة بتنسيق النطاق العكسي مثل com.acme واسم artifact بأحرف صغيرة وشرطات مثل bookstore-api.
  • التغليف: Jar لمعظم التطبيقات (يُجمَّع الخادم المدمج بداخله). اختر War فقط حين يتعين عليك النشر على حاوية servlet خارجية.
  • إصدار Java: طابق JDK الخاص بك. الإصدار 21 (LTS) هو الخيار الأفضل حاليًا.
  • التبعيات (الـ Starters): أضف ما تحتاجه الآن؛ يمكنك دائمًا إضافة المزيد إلى pom.xml لاحقًا.
ابدأ بالحد الأدنى. أضف فقط الـ starters التي تحتاجها بيقين اليوم. كل starter على الـ classpath يُفعّل auto-configuration ويزيد من وقت الإقلاع. إضافة تبعية أسهل بكثير من فك تبعية متشعبة.

انقر Generate، فك ضغط الأرشيف، وافتحه في بيئة التطوير. المشروع يُترجَم ويعمل فور الإنشاء — لا شيء يحتاج إعدادًا قبل أول ./mvnw spring-boot:run.

تخطيط المشروع القياسي

يُنتج Spring Initializr مشروع Maven أو Gradle يتبع اتفاقية دليل Java القياسية. مشروع تم توليده حديثًا يبدو هكذا:

bookstore-api/ ├── .mvn/wrapper/ ← Maven Wrapper (لا يتطلب Maven محليًا) ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/acme/bookstoreapi/ │ │ │ └── BookstoreApiApplication.java ← الفئة الرئيسية │ │ └── resources/ │ │ ├── application.properties ← إعدادات وقت التشغيل │ │ ├── static/ ← يُخدَّم كما هو (CSS، JS، صور) │ │ └── templates/ ← قوالب Thymeleaf / FreeMarker │ └── test/ │ └── java/ │ └── com/acme/bookstoreapi/ │ └── BookstoreApiApplicationTests.java ├── mvnw ← سكريبت Maven Wrapper (Unix) ├── mvnw.cmd ← سكريبت Maven Wrapper (Windows) ├── pom.xml ← واصف البناء └── HELP.md

بعض النقاط الجديرة بالملاحظة:

  • Maven Wrapper (mvnw) يُثبّت إصدارًا محددًا من Maven للمشروع، فيستخدم كل مطور وكل خادم CI أداة البناء ذاتها بالضبط دون الحاجة إلى تثبيت محلي. شغّله بـ ./mvnw spring-boot:run على macOS/Linux أو mvnw.cmd spring-boot:run على Windows.
  • src/main/resources/static/ يُخدَّم مباشرةً بواسطة الخادم المدمج. ملف في static/favicon.ico يكون متاحًا عبر http://localhost:8080/favicon.ico.
  • src/main/resources/templates/ هو الموقع الافتراضي لقوالب العرض من جانب الخادم. يُهم فقط إذا أضفت starter لمحرك قوالب.
  • شجرة مصادر الاختبار تعكس شجرة المصادر الرئيسية. BookstoreApiApplicationTests المُوَلَّد يحمّل سياق Spring الكامل — إنه اختبار دخان تكاملي وليس اختبار وحدة.
تسمية الحزم مهمة. يبدأ Spring Boot مسح المكونات (الفئات المُزيَّنة بـ @Component أو @Service أو @Repository أو @Controller إلخ) من الحزمة التي تحتوي على الفئة الرئيسية وجميع الحزم الفرعية. ضع الفئة الرئيسية في جذر الحزمة الأساسية — ليس داخل حزمة فرعية — لتغطية المسح لكل شيء تلقائيًا.

ملف pom.xml — ما يولّده Initializr

يحتوي pom.xml المُوَلَّد على إضافتين هيكليتين فوق مشروع Maven العادي: يرث من spring-boot-starter-parent ويتضمن Spring Boot Maven plugin.

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.3.0</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- لا <version> — موروثة من BOM الأب --> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>

يستورد spring-boot-starter-parent قائمة مواد Spring Boot BOM التي تحدد إصدارات مُدارة لمئات المكتبات. لهذا لا تحتاج مدخلات <dependency> إلى وسم <version> — تُوفّره قائمة BOM تلقائيًا بإصدار متوافق ومختبر. يُضيف Maven plugin هدف spring-boot:run ويُعيد حزم JAR إلى fat JAR تنفيذي يجمع كل التبعيات بداخله لتتمكن من نشره بأمر java -jar واحد.

الفئة الرئيسية — @SpringBootApplication

يولّد Spring Initializr فئة رئيسية واحدة بالضبط. إنها صغيرة لكنها تحمل معنى كبيرًا:

package com.acme.bookstoreapi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class BookstoreApiApplication { public static void main(String[] args) { SpringApplication.run(BookstoreApiApplication.class, args); } }

@SpringBootApplication هو تعليق توضيحي مُركَّب — اختصار لثلاثة تعليقات مُطبَّقة معًا:

  • @SpringBootConfiguration — يُعلّم هذه الفئة كمصدر إعداد (يعادل @Configuration في Spring). يمكنك تعريف دوال @Bean مباشرةً هنا، رغم أن معظم الفرق تحتفظ بالفئة الرئيسية نظيفة وتضع الـ beans في فئات @Configuration مخصصة.
  • @EnableAutoConfiguration — يأمر Spring Boot بفحص الـ classpath وتفعيل الإعدادات الافتراضية المنطقية لكل ما يجده. إذا كان spring-boot-starter-web موجودًا، يُهيئ Tomcat مدمجًا وDispatcherServlet. يُغطّى الـ auto-configuration بعمق في الدرس الرابع.
  • @ComponentScan — يمسح الحزمة الحالية (والحزم الفرعية) بحثًا عن المكونات التي يديرها Spring. هذه الآلية هي ما يكتشف فئات @Service و@Repository و@RestController.

تؤدي SpringApplication.run(BookstoreApiApplication.class, args) عملية الإقلاع الفعلية:

  1. تُنشئ ApplicationContext مناسبة للبيئة المكتشفة (servlet أو reactive أو لا شيء).
  2. تُسجّل جميع الـ beans المكتشفة وتُطبّق الـ auto-configuration.
  3. تُشغّل الخادم المدمج (إذا كان web starter موجودًا).
  4. تُطلق ApplicationReadyEvent حتى يتمكن المستمعون والـ runners من تنفيذ المنطق اللاحق للإقلاع.
لا تُعيد تسمية الفئة الرئيسية أو تنقلها دون تحديث حزمة الفحص الأساسية. إذا نقلتها إلى حزمة فرعية مثل com.acme.bookstoreapi.config، سيمسح @ComponentScan فقط com.acme.bookstoreapi.config وما ينبع منها — مفوّتًا الـ beans في الحزم المجاورة. إما أبق الفئة الرئيسية في الجذر، أو اضبط صراحةً @SpringBootApplication(scanBasePackages = "com.acme.bookstoreapi").

تشغيل التطبيق

تمتلك ثلاث طرق متكافئة لتشغيل التطبيق خلال التطوير:

  • Maven Wrapper: ./mvnw spring-boot:run — يُترجم ويُشغّل بأمر واحد، مريح للتكرار السريع.
  • تهيئة تشغيل بيئة التطوير: انقر بزر الفأرة الأيمن على الفئة الرئيسية ثم Run. يكتشف كل من IntelliJ IDEA وVS Code تطبيقات Spring Boot ويُنشئان تهيئات تشغيل جاهزة تلقائيًا.
  • Fat JAR: ./mvnw package ثم java -jar target/bookstore-api-0.0.1-SNAPSHOT.jar — هذا هو نموذج النشر في الإنتاج.

مع وجود spring-boot-starter-web على الـ classpath ستظهر مخرجات مثل التالي ويستمع التطبيق على المنفذ 8080:

. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.3.0) Started BookstoreApiApplication in 1.432 seconds

الخلاصة

يُولّد Spring Initializr مشروع Maven أو Gradle بتخطيط اتفاقي ثابت. تمتلك الفئة الرئيسية المُزيَّنة بـ @SpringBootApplication مسح المكونات وتفعيل الـ auto-configuration ونقطة الدخول للإقلاع — كل ذلك في مكان واحد. إنّ فهم هذا السقالة — والخيارات المبنية فيها — يعني قدرتك على تعديله بشكل مدروس لا بأسلوب التجربة والخطأ. في الدرس القادم ستكتشف كيف تُبقي الـ starters وقائمة BOM إدارة التبعيات تحت السيطرة.