أساسيات Spring Boot

خصائص التطبيق

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

خصائص التطبيق

كل تطبيق Spring Boot غير بديهي يحتاج إلى سلوك مختلف في بيئات مختلفة: قاعدة بيانات المطوّر على الحاسوب المحمول ليست قاعدة الإنتاج، وخادم البريد التجريبي ليس مُرسِل SMTP الحقيقي، وتسجيل الأحداث على مستوى debug غير ملائم في الإنتاج. يحلّ Spring Boot هذه المشكلة من خلال نظام إعداد موحّد متعدد الطبقات يرتكز على application.properties ونسخته YAML الأخ application.yml. يغطّي هذا الدرس آلية عمل هذا النظام، وما يمكن إعداده، والأنماط التي يعتمدها المطوّرون المحترفون يومًا بعد يوم.

أين يبحث Spring Boot عن الإعداد

يحلّ Spring Boot الإعدادات من مصادر متعددة ويدمجها وفق ترتيب أولوية محدد (الرقم الأعلى يكسب):

  1. القيم الافتراضية المشفّرة داخل الإعدادات التلقائية (auto-configurations)
  2. ملف application.properties أو application.yml داخل حزمة JAR (في جذر classpath، أي src/main/resources/)
  3. الملفات الخاصة بالـ Profile: application-{profile}.properties على classpath
  4. نفس الملفات خارج ملف JAR، في دليل العمل
  5. متغيرات البيئة في نظام التشغيل
  6. خصائص نظام JVM (مثال: -Dserver.port=9090)
  7. وسائط سطر الأوامر (مثال: --server.port=9090)
الفكرة المحورية: وسائط سطر الأوامر ومتغيرات البيئة تتجاوز كل ما دونها في القائمة. هذا يعني أن ملف JAR يُشحن بإعدادات افتراضية معقولة في src/main/resources/application.properties، وتستطيع العمليات تجاوز أي قيمة وقت التشغيل دون إعادة ترجمة الكود.

Properties مقابل YAML — أيهما تختار

ملفات .properties تستخدم أزواج مفتاح-قيمة مسطّحة:

spring.datasource.url=jdbc:postgresql://localhost:5432/shop spring.datasource.username=app spring.datasource.password=secret spring.datasource.hikari.maximum-pool-size=10

ملفات .yml (YAML) تعبّر عن المعلومات ذاتها كشجرة متداخلة:

spring: datasource: url: jdbc:postgresql://localhost:5432/shop username: app password: secret hikari: maximum-pool-size: 10

كلاهما متكافئ. YAML أكثر قابلية للقراءة في الهياكل المتداخلة بعمق ويدعم القوائم بشكل نظيف؛ أما .properties فأبسط في البحث (grep) وأكثر ألفةً لمطوّري Java المخضرمين. يدعم Spring Boot 3 الصيغتين. لا تخلطهما في المشروع نفسه — اختر واحدة والتزم بها.

مزلق YAML: YAML حساس للمسافات البيضاء. علامة tab واحدة في غير مكانها (بدلًا من مسافات) أو مستوى مسافة بادئة خاطئ ينتج قيمة مختلفة أو فشل في بدء التشغيل دون أي تحذير واضح. استخدم IDE يدعم YAML وفعّل التحقق من المخطط.

أكثر خصائص Spring Boot استخدامًا

يأتي Spring Boot مع آلاف مفاتيح الإعداد الموثّقة في مرجع Common Application Properties. أكثرها شيوعًا في العمل اليومي:

الخادم

server.port=8080 server.servlet.context-path=/api server.shutdown=graceful spring.lifecycle.timeout-per-shutdown-phase=30s

مصدر البيانات و JPA

spring.datasource.url=jdbc:postgresql://localhost:5432/shop spring.datasource.username=app spring.datasource.password=secret spring.datasource.driver-class-name=org.postgresql.Driver spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=false spring.jpa.open-in-view=false

تسجيل الأحداث

logging.level.root=INFO logging.level.com.example.shop=DEBUG logging.file.name=logs/app.log

Spring MVC

spring.mvc.format.date=iso spring.mvc.format.date-time=iso spring.web.resources.add-mappings=false

ربط الخصائص بفئة إعداد مخصصة

توزيع تعليق @Value("${my.key}") في كل أرجاء الكود هش وصعب الاختبار. الأسلوب المحترف في Spring Boot 3 هو @ConfigurationProperties: تعرّف سجلًّا (record) أو فئة Java عادية، تضع عليه التعليق، فيربط Spring تلقائيًا الخصائص ذات البادئة المطابقة من application.properties إلى حقوله — مع تحويل الأنواع والتحقق من الصحة وإكمال تلقائي في IDE.

# application.properties app.mail.host=smtp.example.com app.mail.port=587 app.mail.from=noreply@example.com app.mail.rate-limit=100
package com.example.shop.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.bind.DefaultValue; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; @ConfigurationProperties(prefix = "app.mail") public record MailProperties( @NotBlank String host, @DefaultValue("587") int port, @NotBlank String from, @Min(1) int rateLimit ) {}

سجّله في فئة التطبيق الرئيسية (أو أي فئة @Configuration):

@SpringBootApplication @EnableConfigurationProperties(MailProperties.class) public class ShopApplication { public static void main(String[] args) { SpringApplication.run(ShopApplication.class, args); } }

حقنه في أي مكان كمعامل مُنشئ عادي (Spring Boot يسجّله تلقائيًا كـ bean):

@Service public class MailService { private final MailProperties mail; public MailService(MailProperties mail) { this.mail = mail; } public void send(String to, String subject, String body) { // mail.host()، mail.port()، mail.from() كلها آمنة من حيث النوع System.out.printf("Sending from %s via %s:%d%n", mail.from(), mail.host(), mail.port()); } }
لماذا تتناسب السجلات (records) بشكل مثالي: يستخدم @ConfigurationProperties على السجل المُنشئ القانوني، ومن ثَمّ يكون كل خاصية مطلوبة إلا إذا زُوِّدت بـ @DefaultValue. النتيجة: كائن إعداد ثابت (immutable) وآمن من القيم الخالية يمكن حقنه واختباره دون محاكاة أي سياق Spring.

الـ Profiles — إعداد خاص بكل بيئة

تتيح لك الـ Profiles الاحتفاظ بمجموعات إعداد منفصلة لـ dev وtest وprod دون تغيير سطر كود Java واحد. أنشئ ملفًا خاصًا بالـ Profile:

  • application-dev.properties — إعدادات المطوّر (قاعدة بيانات H2 في الذاكرة، تسجيل مسهب)
  • application-prod.properties — إعدادات الإنتاج (PostgreSQL، مستوى تسجيل INFO، بلا طباعة SQL)
# application-dev.properties spring.datasource.url=jdbc:h2:mem:devdb;DB_CLOSE_DELAY=-1 spring.datasource.username=sa spring.datasource.password= spring.jpa.show-sql=true logging.level.root=DEBUG
# application-prod.properties spring.datasource.url=jdbc:postgresql://db.internal:5432/shop spring.datasource.username=${DB_USER} spring.datasource.password=${DB_PASS} spring.jpa.show-sql=false logging.level.root=WARN

تفعيل الـ Profile وقت التشغيل — بلا إعادة ترجمة:

# علم JVM java -jar shop.jar -Dspring.profiles.active=prod # متغير البيئة (مفيد في الحاويات) SPRING_PROFILES_ACTIVE=prod java -jar shop.jar
لا تُودع الأسرار في نظام إدارة الإصدار أبدًا. النمط ${DB_PASS} داخل application-prod.properties يخبر Spring Boot بقراءة القيمة من متغير بيئة نظام التشغيل باسم DB_PASS. استخدم هذا النمط لجميع كلمات المرور ومفاتيح API والرموز المميزة. الأسرار في ملفات .properties المُودَعة في Git تُشكّل خطرًا أمنيًا بالغ الخطورة.

التعليق @Value — متى لا يزال منطقيًا

يفيد @Value في حقن خاصية واحدة في bean حين تبدو فئة @ConfigurationProperties الكاملة مبالغًا فيها:

@Component public class AppInfo { @Value("${app.version:unknown}") private String version; public String getVersion() { return version; } }

اللاحقة :unknown هي القيمة الافتراضية إن كان المفتاح غائبًا. استخدم @Value باعتدال — إنه يتجاوز أمان النوع وأصعب في الاختبار. فضّل @ConfigurationProperties لأي مجموعة من الإعدادات المترابطة.

الخلاصة

نظام إعداد Spring Boot متعدد الطبقات: إعدادات افتراضية داخل JAR، تجاوزات في ملفات خاصة بالـ Profile، وتجاوزات نهائية عبر متغيرات البيئة ووسائط سطر الأوامر. اكتب الإعدادات المشتركة في application.properties، والخاصة بالبيئة في application-{profile}.properties، واربط الإعدادات المترابطة في سجلات @ConfigurationProperties آمنة من حيث النوع. الأسرار لا تعيش في ملفات أبدًا — تأتي من البيئة وقت التشغيل. أتقن هذا النظام ونادرًا ما ستحتاج إلى تغيير الكود المُترجَم لمجرد تعديل سلوك التطبيق.