انتقل إلى المحتوى الرئيسي

الفصل 3: التكوين باستخدام application.properties و application.yml

المقدمة​

التكوين هو جانب أساسي من أي تطبيق. يوفر Spring Boot نظام تكوين قوي ومرن يسمح بتخصيص سلوك التطبيق دون تعديل الكود.

أهداف الفصل​

في نهاية هذا الفصل، ستكون قادرًا على:

  • تكوين تطبيق باستخدام application.properties و application.yml
  • استخدام خصائص Spring Boot المحددة مسبقًا
  • إنشاء خصائص مخصصة
  • إدارة البيئات المختلفة باستخدام ملفات التعريف
  • توسيع التكوين

ملفات التكوين​

الموقع​

يبحث Spring Boot عن ملفات التكوين بالترتيب التالي:

ترتيب الأولوية (من الأعلى إلى الأدنى):

  1. file:./config/application.properties
  2. file:./config/application.yml
  3. file:./application.properties
  4. file:./application.yml
  5. classpath:/config/application.properties
  6. classpath:/config/application.yml
  7. classpath:/application.properties
  8. classpath:/application.yml

في الممارسة العملية: ضع ملفاتك في src/main/resources/


تنسيق application.properties​

بناء الجملة الأساسي​

التنسيق:

cle=valeur

الخصائص:

  • تنسيق بسيط للزوج المفتاح-القيمة
  • لا يوجد مسافة بادئة
  • تعليقات مع #
  • تكرار البادئات

مثال كامل​

# تكوين الخادم
server.port=8080
server.servlet.context-path=/api

# اسم التطبيق
spring.application.name=greeting-app

# تكوين قاعدة البيانات
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=postgres
spring.datasource.password=secret
spring.datasource.driver-class-name=org.postgresql.Driver

# تكوين JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

# تكوين السجلات
logging.level.root=INFO
logging.level.com.example=DEBUG
logging.level.org.springframework.web=DEBUG
logging.file.name=logs/application.log

# تكوين Jackson (JSON)
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=America/Montreal
spring.jackson.serialization.indent-output=true

المزايا والعيوب​

المزايا:

  • تنسيق بسيط ومعروف على نطاق واسع
  • متوافق مع Java Properties
  • لا توجد تبعية خارجية

العيوب:

  • متكرر للهياكل الهرمية
  • أقل قابلية للقراءة للتكوينات المعقدة

تنسيق application.yml​

بناء الجملة الأساسي​

التنسيق: YAML (YAML Ain't Markup Language)

الخصائص:

  • تنسيق هرمي مع مسافة بادئة
  • المسافة البادئة = 2 أو 4 مسافات (بدون علامات تبويب)
  • هيكل شجري
  • أكثر إيجازًا

مثال كامل​

# تكوين الخادم
server:
port: 8080
servlet:
context-path: /api

# اسم التطبيق
spring:
application:
name: greeting-app

# تكوين قاعدة البيانات
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: secret
driver-class-name: org.postgresql.Driver

# تكوين JPA
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.PostgreSQLDialect

# تكوين Jackson
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: America/Montreal
serialization:
indent-output: true

# تكوين السجلات
logging:
level:
root: INFO
com.example: DEBUG
org.springframework.web: DEBUG
file:
name: logs/application.log

المزايا والعيوب​

المزايا:

  • أكثر قابلية للقراءة للهياكل المعقدة
  • أقل تكرارًا
  • دعم القوائم والخرائط
  • تنسيق حديث

العيوب:

  • حساس للمسافة البادئة
  • أخطاء بناء الجملة أكثر شيوعًا
  • يتطلب تبعية SnakeYAML (مضمنة افتراضيًا)

مقارنة properties مقابل yml​

نفس التكوين في كلا التنسيقين​

application.properties:

spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=postgres
spring.datasource.password=secret

application.yml:

spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: secret

جدول المقارنة​

المعيارpropertiesyml
قابلية القراءة⭐⭐⭐⭐⭐⭐⭐⭐
البساطة⭐⭐⭐⭐⭐⭐⭐⭐
الهيكلمسطحهرمي
التكراركثيرقليل
القوائمصعبسهل
التوافقعالمييتطلب محلل
الأخطاءنادرةالمسافة البادئة

التوصية: استخدم .yml للتكوينات المعقدة، .properties للتكوينات البسيطة.


خصائص Spring Boot الشائعة​

1. تكوين الخادم​

server:
port: 8080 # منفذ الخادم
servlet:
context-path: /api # مسار الأساس
compression:
enabled: true # ضغط GZIP
error:
include-message: always # تضمين رسائل الخطأ

2. تكوين قاعدة البيانات​

PostgreSQL​

spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: secret
driver-class-name: org.postgresql.Driver

MySQL​

spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: secret
driver-class-name: com.mysql.cj.jdbc.Driver

H2 (قاعدة بيانات في الذاكرة - اختبارات)​

spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
h2:
console:
enabled: true # وحدة تحكم H2 قابلة للوصول
path: /h2-console

3. تكوين JPA/Hibernate​

spring:
jpa:
hibernate:
ddl-auto: update # none, validate, update, create, create-drop
show-sql: true # عرض استعلامات SQL
properties:
hibernate:
format_sql: true # تنسيق الاستعلامات
dialect: org.hibernate.dialect.PostgreSQLDialect
use_sql_comments: true # تعليق الاستعلامات

قيم ddl-auto:

القيمةالوصفالاستخدام
noneلا يوجد إجراءالإنتاج
validateالتحقق من صحة المخطط فقطالإنتاج
updateتحديث المخططالتطوير
createإنشاء المخطط عند بدء التشغيلالاختبارات
create-dropإنشاء ثم حذفالاختبارات

4. تكوين السجلات​

logging:
level:
root: INFO # المستوى العام
com.example: DEBUG # تطبيقك
org.springframework.web: DEBUG # Spring Web
org.hibernate.SQL: DEBUG # استعلامات SQL
org.hibernate.type: TRACE # معلمات SQL
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss} - %msg%n'
file:
name: logs/application.log # ملف السجل
max-size: 10MB # الحجم الأقصى لكل ملف

مستويات السجل:

TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF

5. تكوين Jackson (JSON)​

spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: America/Montreal
serialization:
indent-output: true # JSON مدمج
write-dates-as-timestamps: false
deserialization:
fail-on-unknown-properties: false

6. تكوين DevTools​

spring:
devtools:
restart:
enabled: true # إعادة التشغيل التلقائي
livereload:
enabled: true # إعادة تحميل المتصفح

خصائص مخصصة​

إنشاء خصائص مخصصة​

application.yml:

app:
name: Greeting Application
version: 1.0.0
admin:
email: admin@example.com
phone: +1-514-123-4567
security:
jwt-secret: mySecretKey123
jwt-expiration: 86400000 # 24 ساعة بالمللي ثانية

الحقن باستخدام @Value​

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class AppConfig {

@Value("${app.name}")
private String appName;

@Value("${app.version}")
private String appVersion;

@Value("${app.admin.email}")
private String adminEmail;

public void printConfig() {
System.out.println("Application: " + appName);
System.out.println("Version: " + appVersion);
System.out.println("Admin Email: " + adminEmail);
}
}

فئة التكوين باستخدام @ConfigurationProperties​

النهج الموصى به للعديد من الخصائص:

application.yml:

app:
security:
jwt-secret: mySecretKey123
jwt-expiration: 86400000
allowed-origins:
- http://localhost:3000
- http://localhost:4200

فئة التكوين:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;

@Component
@ConfigurationProperties(prefix = "app.security")
public class SecurityProperties {

private String jwtSecret;
private Long jwtExpiration;
private List<String> allowedOrigins;

// Getters et Setters
public String getJwtSecret() {
return jwtSecret;
}

public void setJwtSecret(String jwtSecret) {
this.jwtSecret = jwtSecret;
}

public Long getJwtExpiration() {
return jwtExpiration;
}

public void setJwtExpiration(Long jwtExpiration) {
this.jwtExpiration = jwtExpiration;
}

public List<String> getAllowedOrigins() {
return allowedOrigins;
}

public void setAllowedOrigins(List<String> allowedOrigins) {
this.allowedOrigins = allowedOrigins;
}
}

الاستخدام:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AuthService {

@Autowired
private SecurityProperties securityProperties;

public void generateToken() {
String secret = securityProperties.getJwtSecret();
Long expiration = securityProperties.getJwtExpiration();
// Logique de génération de token
}
}

إدارة ملفات التعريف​

مفهوم ملفات التعريف​

تسمح ملفات التعريف بوجود تكوينات مختلفة حسب البيئة.

إنشاء ملفات التعريف​

هيكل الملفات:

src/main/resources/
├── application.yml # التكوين المشترك
├── application-dev.yml # التطوير
├── application-test.yml # الاختبارات
└── application-prod.yml # الإنتاج

التكوين حسب ملف التعريف​

application.yml (مشترك):

spring:
application:
name: greeting-app

app:
name: Greeting Application

application-dev.yml:

server:
port: 8080

spring:
datasource:
url: jdbc:h2:mem:testdb
h2:
console:
enabled: true

logging:
level:
root: DEBUG

application-test.yml:

server:
port: 8081

spring:
datasource:
url: jdbc:h2:mem:testdb

logging:
level:
root: INFO

application-prod.yml:

server:
port: 80

spring:
datasource:
url: jdbc:postgresql://prod-db.example.com:5432/mydb
username: ${DB_USERNAME} # متغير البيئة
password: ${DB_PASSWORD}

logging:
level:
root: WARN
file:
name: /var/log/app/application.log

تفعيل ملف شخصي​

الطريقة 1: في application.yml

spring:
profiles:
active: dev

الطريقة 2: سطر الأوامر

java -jar app.jar --spring.profiles.active=prod

الطريقة 3: متغير البيئة

export SPRING_PROFILES_ACTIVE=prod
java -jar app.jar

الطريقة 4: في IDE

VS Code (launch.json):

{
"configurations": [
{
"type": "java",
"name": "Spring Boot App",
"request": "launch",
"mainClass": "com.example.greeting.GreetingApplication",
"args": "--spring.profiles.active=dev"
}
]
}

ملفات شخصية متعددة​

يمكنك تفعيل ملفات شخصية متعددة:

java -jar app.jar --spring.profiles.active=dev,local

ترتيب الأولوية: ملف التعريف الأخير له الأولوية


متغيرات البيئة​

الاستخدام​

يمكن لـ Spring Boot قراءة متغيرات البيئة:

application.yml:

spring:
datasource:
url: ${DATABASE_URL:jdbc:postgresql://localhost:5432/mydb}
username: ${DATABASE_USER:postgres}
password: ${DATABASE_PASSWORD:secret}

بناء الجملة: ${NOM_VARIABLE:valeur_par_defaut}

تعيين المتغيرات​

Windows (CMD):

set DATABASE_URL=jdbc:postgresql://prod-server:5432/mydb
set DATABASE_USER=admin
set DATABASE_PASSWORD=supersecret
java -jar app.jar

Windows (PowerShell):

$env:DATABASE_URL="jdbc:postgresql://prod-server:5432/mydb"
$env:DATABASE_USER="admin"
$env:DATABASE_PASSWORD="supersecret"
java -jar app.jar

Linux/macOS:

export DATABASE_URL=jdbc:postgresql://prod-server:5432/mydb
export DATABASE_USER=admin
export DATABASE_PASSWORD=supersecret
java -jar app.jar

التكوين الخارجي​

ملف تكوين خارجي​

يمكن لـ Spring Boot تحميل ملفات تكوين خارجية:

الهيكل:

/opt/app/
├── app.jar
└── config/
└── application.yml

التشغيل:

java -jar /opt/app/app.jar

سيجد Spring Boot تلقائيًا /opt/app/config/application.yml

تحديد ملف​

java -jar app.jar --spring.config.location=file:/path/to/config/

الخصائص الحساسة​

تأمين كلمات المرور​

ممارسة سيئة:

spring:
datasource:
password: supersecret123 # ❌ كلمة مرور واضحة

ممارسات جيدة:

1. متغيرات البيئة:

spring:
datasource:
password: ${DATABASE_PASSWORD} # ✅ متغير البيئة

2. Spring Cloud Config Server:

  • مركزية التكوين
  • تشفير الخصائص الحساسة

3. HashiCorp Vault:

  • إدارة احترافية للأسرار

4. ملفات .env (للتطوير فقط):

DATABASE_PASSWORD=secret

مهم: لا تقم أبدًا بارتكاب كلمات المرور في Git!


تمارين عملية​

التمرين 1: التكوين الأساسي​

الهدف: تكوين المنفذ واسم التطبيق

التعليمات:

  1. قم بإنشاء مشروع Spring Boot
  2. في application.properties، قم بتكوين:
    • المنفذ: 8081
    • الاسم: "My Greeting App"
  3. ابدأ التطبيق
  4. تحقق من أن الخادم يبدأ على المنفذ 8081

التمرين 2: تحويل properties → yml​

الهدف: تحويل ملف properties إلى yml

ملف properties المعطى:

server.port=8080
spring.application.name=user-service
spring.datasource.url=jdbc:postgresql://localhost:5432/users
spring.datasource.username=admin
spring.jpa.show-sql=true

المطلوب: تحويل إلى تنسيق YAML

التمرين 3: خصائص مخصصة​

الهدف: إنشاء واستخدام خصائص مخصصة

التعليمات:

  1. أضف في application.yml:
    app:
    welcome-message: Bienvenue!
    max-users: 100
  2. قم بإنشاء وحدة تحكم تعرض هذه القيم
  3. اختبر

التمرين 4: ملفات التعريف​

الهدف: إنشاء ملفات شخصية dev و prod

التعليمات:

  1. قم بإنشاء application-dev.yml:
    • المنفذ: 8080
    • السجلات: DEBUG
  2. قم بإنشاء application-prod.yml:
    • المنفذ: 80
    • السجلات: WARN
  3. اختبر تفعيل كل ملف شخصي

أسئلة المراجعة​

  1. ما الفرق بين application.properties و application.yml؟

  2. كيف تقوم بتفعيل ملف شخصي في Spring Boot؟

  3. ما هو ترتيب الأولوية لملفات التكوين؟

  4. كيف تقوم بحقن خاصية مخصصة في فئة؟

  5. ما هي التعليمة التي تستخدمها لفئة تكوين تحتوي على عدة خصائص؟

  6. كيف تستخدم متغير بيئة في application.yml؟

  7. ما هي القيم الممكنة لـ spring.jpa.hibernate.ddl-auto؟

  8. لماذا لا يجب أبدًا ارتكاب كلمات المرور في application.properties؟


ملخص الفصل​

النقاط الرئيسية​

  • يدعم Spring Boot .properties و .yml
  • .yml أكثر قابلية للقراءة للهياكل المعقدة
  • تسمح ملفات التعريف بتكوينات حسب البيئة
  • @Value لخاصية واحدة، @ConfigurationProperties لعدة خصائص
  • استخدام متغيرات البيئة للبيانات الحساسة
  • لا تقم أبدًا بارتكاب كلمات المرور

الممارسات الجيدة​

  • استخدام ملفات التعريف لكل بيئة
  • توسيع التكوينات الحساسة
  • توثيق الخصائص المخصصة
  • توفير قيم افتراضية
  • استخدام أسماء خصائص وصفية
  • فصل التكوين المشترك عن التكوين الخاص

الخطوات التالية​

في الفصل التالي، سندرس:

الفصل 4: التعليميات الأساسية

  • @SpringBootApplication
  • @RestController مقابل @Controller
  • @GetMapping, @PostMapping، إلخ.
  • @Autowired وحقن التبعية
  • @Component, @Service, @Repository

العودة إلى الوحدة 2