تطبيق Spring Boot الأول الخاص بك
تعليق @SpringBootApplication وحده كافٍ لتشغيل التطبيق بالكامل—سحر Spring Boot يكمن في الجمع الذكي بين ثلاثة تعليقات.
1. ما ستتعلمه
- مبادئ تفكيك وتجميع تعليق
@SpringBootApplication - طريقة التشغيل الرئيسية
main()وتدفق تنفيذSpringApplication.run() - تنسيقات ملفات التهيئة
application.propertiesمقابلapplication.yml - تخصيص شعار Spring Boot وتفسير سجلات التشغيل
- تشغيل واجهة "Hello OrderFlow" الأولى
2. قصة حقيقية عن مشروع جديد
(1) نقطة الألم: يستغرق إعداد المشروع نصف يوم
تذكرت Alice تجربتها مع Spring MVC التقليدي عندما بدأت للتو: إنشاء مشروع يتطلب تهيئة web.xml، وapplicationContext.xml، وspring-mvc.xml، بالإضافة إلى تثبيت Tomcat وتهيئة مصدر بيانات JNDI. مجرد تشغيل المشروع كان يستغرق نصف يوم، ناهيك عن استكشاف أخطاء ترتيب التشغيل ومشاكل تحميل Beans.
(2) حل Spring Boot
Spring Boot يتطلب تعليقاً واحداً وطريقة رئيسية واحدة فقط:
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication.run(OrderFlowApplication.class, args);
}
}
(3) العوائد
استخدمت Alice مشروع Spring Boot لإنشاء OrderFlow. استغرق الأمر 5 دقائق فقط من الصفر حتى أول استجابة API—بدون XML، بدون حاوية خارجية، وسجلات التشغيل واضحة وسهلة القراءة.
3. تفكيك تعليق @SpringBootApplication
(1) مجموعة من ثلاثة تعليقات
@SpringBootApplication هو تعليق مركب يكافئ استخدام التعليقات الثلاثة التالية في وقت واحد:
graph TB
A["@SpringBootApplication"] --> B["@SpringBootConfiguration"]
A --> C["@EnableAutoConfiguration"]
A --> D["@ComponentScan"]
B --> B1["يحدد الصنف كمصدر<br/>لتهيئة Bean"]
C --> C1["يُفعّل التهيئة التلقائية<br/>بناءً على مسار الأصناف"]
D --> D1["يمسح المكونات<br/>في شجرة الحزمة نفسها"]
| التعليق | الوظيفة | التدوين التقليدي المكافئ |
|---|---|---|
@SpringBootConfiguration |
تحديد الصنف الحالي كصنف تهيئة | @Configuration |
@EnableAutoConfiguration |
تفعيل التهيئة التلقائية | @EnableAutoConfiguration |
@ComponentScan |
مسح المكونات | <context:component-scan> |
(2) قواعد مسح @ComponentScan
@ComponentScan يغطي بشكل افتراضي الحزمة التي تحتوي على صنف التشغيل الرئيسي وجميع حزمها الفرعية.
com.orderflow ← الحزمة التي تحتوي على صنف التشغيل الرئيسي
├── OrderFlowApplication.java ← @SpringBootApplication
├── controller/ ← يتم مسحها بواسطة @ComponentScan
│ └── OrderController.java
├── service/ ← يتم مسحها بواسطة @ComponentScan
│ └── OrderService.java
└── repository/ ← يتم مسحها بواسطة @ComponentScan
└── OrderRepository.java
com.other ← ⚠️ غير مشمول في المسح!
4. عملية تشغيل SpringApplication.run()
(1) تسلسل التشغيل
عملية تنفيذ SpringApplication.run() هي خط أنابيب مصمم بعناية:
sequenceDiagram
participant Main as main()
participant SA as SpringApplication
participant Ctx as ApplicationContext
participant Bean as Beans
Main->>SA: new SpringApplication()
SA->>SA: استنتاج المصادر الأساسية
SA->>SA: التحقق من نوع تطبيق الويب
SA->>SA: تحميل المُهيئات والمستمعين
Main->>SA: run(args)
SA->>SA: إنشاء سياق التشغيل الأولي
SA->>SA: إعداد البيئة
SA->>SA: طباعة الشعار
SA->>Ctx: إنشاء ApplicationContext
SA->>Ctx: إعداد السياق (تسجيل المصادر)
SA->>Ctx: تحديث السياق
Ctx->>Bean: إنشاء مثيلات Beans
Ctx->>Bean: التهيئة التلقائية
SA->>SA: استدعاء Runners
SA->>Main: إرجاع ApplicationContext
(2) تحديد نوع تطبيق الويب
Spring Boot يكتشف نوع التطبيق تلقائياً:
| الشرط | النوع | الحاوية المستخدمة |
|---|---|---|
مسار الأصناف يحتوي على spring-webmvc |
SERVLET | Tomcat / Jetty / Undertow |
مسار الأصناف يحتوي على spring-webflux وليس spring-webmvc |
REACTIVE | Netty |
| لا شيء | NONE | بدون حاويات مدمجة |
(1) ▶ مثال: تخصيص تشغيل SpringApplication
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(OrderFlowApplication.class);
app.setBannerMode(Banner.Mode.CONSOLE);
app.setWebApplicationType(WebApplicationType.SERVLET);
app.run(args);
}
}
الناتج:
// التنفيذ ناجح
5. تنسيق ملف التهيئة
(1) Properties مقابل YAML
Spring Boot يدعم تنسيقي ملفات تهيئة متكافئين وظيفياً لكنهما يختلفان في الصياغة.
(1) ▶ مثال: كيفية كتابة application.properties
server.port=8080
spring.application.name=orderflow-service
spring.datasource.url=jdbc:mysql://localhost:3306/orderflow
spring.datasource.username=root
spring.datasource.password=secret
spring.jpa.hibernate.ddl-auto=update
الناتج:
// التنفيذ ناجح
(2) ▶ مثال: كيفية كتابة application.yml
server:
port: 8080
spring:
application:
name: orderflow-service
datasource:
url: jdbc:mysql://localhost:3306/orderflow
username: root
password: secret
jpa:
hibernate:
ddl-auto: update
الناتج:
تم تفعيل التهيئة.
| البُعد | Properties | YAML |
|---|---|---|
| الهيكل الهرمي | مفصول بـ . |
المسافة البادئة تدل على التسلسل الهرمي |
| قابلية القراءة | أزواج مفتاح-قيمة بسيطة، مسطحة | هيكل هرمي واضح، مناسب للتداخل |
| دعم القوائم | list[0]=a |
- a أكثر بديهية |
| البادئة المتكررة | يجب تكرارها | بادئة مشتركة في نفس المستوى |
| أداء التحليل | أسرع | أبطأ قليلاً (يتطلب تحليل التسلسل الهرمي) |
| الأولوية | متساوية | متساوية (properties لها الأسبقية عند وجود كليهما) |
(2) مرجع سريع لخيارات التهيئة الشائعة
| خيار التهيئة | القيمة الافتراضية | الوصف |
|---|---|---|
server.port |
8080 | منفذ استماع التطبيق |
spring.application.name |
— | اسم التطبيق |
server.servlet.context-path |
/ | المساق السياقي |
spring.main.banner-mode |
console | وضع عرض الشعار |
spring.jpa.show-sql |
false | طباعة SQL |
logging.level.root |
INFO | مستوى السجل العام |
6. تخصيص الشعار وسجلات التشغيل
(1) شعار مخصص
ضع شعاراً مخصصاً في src/main/resources/banner.txt ليُعرض تلقائياً عند بدء تشغيل Spring Boot.
(1) ▶ مثال: شعار OrderFlow المخصص
____ _ ____ __
/ ___| _ __ __ _| |_ ___ / ___|| | ___ _ __
| | | '_ \ / _` | __/ _ \ \___ \| |/ _ \| '_ \
| |___ | | | | (_| | || __/ ___) | | (_) | | | |
\____||_| |_|\__,_|\__\___| |____/|_|\___/|_| |_|
:: OrderFlow Service :: v${application.version:1.0.0}
:: Spring Boot ${spring-boot.version} ::
الناتج:
التنفيذ ناجح
(2) تفسير سجل التشغيل
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | | || (_| | / / / /
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.2.5)
2024-01-15 10:00:01.123 INFO 12345 --- [main] c.o.OrderFlowApplication : Starting OrderFlowApplication
2024-01-15 10:00:03.456 INFO 12345 --- [main] o.s.b.w.e.t.TomcatWebServer : Tomcat initialized with port 8080 (http)
2024-01-15 10:00:04.789 INFO 12345 --- [main] o.s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories
2024-01-15 10:00:06.012 INFO 12345 --- [main] c.o.OrderFlowApplication : Started in 5.123 seconds
| كلمات السجل الرئيسية | المعنى |
|---|---|
Starting OrderFlowApplication |
تشغيل التطبيق |
Tomcat initialized with port |
بدء Tomcat المدمج |
Bootstrapping Spring Data JPA |
التهيئة التلقائية لمستودع JPA |
Started in X seconds |
اكتمل التشغيل، استغرق |
7. تشغيل واجهة "Hello OrderFlow" الأولى
(1) ▶ مثال: متحكم Hello OrderFlow
package com.orderflow.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class HelloController {
@GetMapping("/api/hello")
public Map<String, String> hello() {
return Map.of(
"message", "Hello, OrderFlow!",
"timestamp", java.time.Instant.now().toString()
);
}
}
الناتج:
HTTP 200 OK
Content-Type: application/json
{"status":"success","data":{}}
$ curl http://localhost:8080/api/hello
{"message":"Hello, OrderFlow!","timestamp":"2024-01-15T10:00:00Z"}
(2) ▶ مثال: استخدام @Value لحقن التهيئة
@RestController
public class HelloController {
@Value("${spring.application.name}")
private String appName;
@GetMapping("/api/info")
public Map<String, String> info() {
return Map.of(
"application", appName,
"javaVersion", System.getProperty("java.version")
);
}
}
الناتج:
// التنفيذ ناجح
8. مثال شامل: تهيئة تشغيل OrderFlow الكاملة
// src/main/java/com/orderflow/OrderFlowApplication.java
package com.orderflow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication.run(OrderFlowApplication.class, args);
}
}
// src/main/java/com/orderflow/controller/OrderFlowController.java
package com.orderflow.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
import java.util.Map;
@RestController
public class OrderFlowController {
@Value("${spring.application.name:orderflow}")
private String appName;
@GetMapping("/api/health")
public Map<String, Object> health() {
return Map.of(
"status", "UP",
"application", appName,
"timestamp", Instant.now()
);
}
}
# src/main/resources/application.yml
server:
port: 8080
spring:
application:
name: orderflow-service
$ curl http://localhost:8080/api/health
{"status":"UP","application":"orderflow-service","timestamp":"2024-01-15T10:00:00Z"}
❓ أسئلة شائعة
properties وYAML؟properties له الأسبقية. يُوصى باستخدام أحدهما فقط لتجنب الارتباك. نوصي بـ YAML لأنه يوفر هيكلاً هرمياً أوضح.spring.main.banner-mode=off في ملف التهيئة، أو app.setBannerMode(Banner.Mode.OFF) في الكود.server.port=8081، أو حدد العملية التي تستخدم المنفذ وأنهها: lsof -i :8080 (Linux/Mac) أو netstat -ano | findstr 8080 (Windows).ddl-auto=validate يسبب اتصالاً بطيئاً بقواعد بيانات بعيدة؛ 3) تهيئات تلقائية غير ضرورية لم يتم استبعادها. استخدم وضع --debug لعرض التفاصيل.<mainClass> في إضافة Maven؛ شغّل الصنف الذي يحتوي على طريقة main مباشرة في IDE؛ إضافة Spring Boot Maven ستكتشفه تلقائياً أثناء التعبئة.📖 ملخص
@SpringBootApplication=@Configuration+@EnableAutoConfiguration+@ComponentScan- يجب وضع صنف التشغيل الرئيسي في الحزمة الجذرية لضمان تغطية مسح المكونات لجميع الحزم الفرعية
SpringApplication.run()يمر بالعملية الكاملة: إعداد البيئة → إنشاء سياق → تحديث → إنشاء مثيلات Bean- YAML وProperties متكافئان وظيفياً؛ YAML هيكل هرمي أوضح، بينما Properties تُحلل أسرع
- تخصيص الشعار باستخدام
banner.txt؛ يمكن لسجلات التشغيل المساعدة في تشخيص مشاكل التشغيل
📝 تمارين
-
تمرين أساسي (الصعوبة: ⭐): أنشئ مشروع Spring Boot، خصّص
banner.txt، غيّر منفذ الخدمة إلى 9090، وبعد تشغيل المشروع، تحقق من إمكانية الوصول إلى نقطة النهاية/api/hello. -
تمرين متقدم (الصعوبة ⭐⭐): استبدل
SpringApplicationBuilderبدلاً منSpringApplication.run()، عطّل الشعار، اضبط مستوى السجل إلى DEBUG، وخصص نقطة نهاية/api/app-infoلإرجاع اسم التطبيق وإصدار Java. -
تحدٍ (الصعوبة: ⭐⭐⭐): نفّذ
StartupListenerوApplicationListener<ApplicationStartedEvent>، سجّل وقت بدء تشغيل التطبيق واطبعه في السجل. فكّر في الدافع التصميمي وراء آلية الأحداث في Spring Boot.



