0Pricing
Java Academy · درس

تعليقات القيود المخصصة

أنشئ تعليق @UniqueEmail مخصصًا مع تنفيذ ConstraintValidator

تعليقات القيود المخصصة درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.

عندما لا تكفي القيود القياسية

تغطي تعليقات Bean Validation التوضيحية القياسية الحالات الشائعة. أما القواعد الخاصة بالمجال (مثل البريد الإلكتروني الفريد، وصحة IBAN، وقوة كلمة المرور)، فتتطلب إنشاء تعليقات توضيحية مخصصة للقيود.

تعريف تعليق القيد التوضيحي

أنشئوا تعليقًا توضيحيًا باستخدام @Constraint(validatedBy = ...)، وعناصر message وgroups وpayload المطلوبة، بالإضافة إلى سياسات الاحتفاظ والاستهداف المناسبة.

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
@Documented
@Constraint(validatedBy = UniqueEmailValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface UniqueEmail {
    String message() default "Email already registered";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

تنفيذ ConstraintValidator

نفّذوا ConstraintValidator<UniqueEmail, String>. وتقرأ أساليب initialize عناصر التعليق التوضيحي، بينما ينفّذ isValid عملية التحقق الفعلية.

@Component
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
    @Autowired private UserRepository repo;
    @Override
    public boolean isValid(String email, ConstraintValidatorContext ctx) {
        if (email == null) return true; // let @NotBlank handle null
        return !repo.existsByEmail(email);
    }
}

استخدام القيد المخصص

طبّقوا التعليق التوضيحي مثل أي قيد قياسي على حقل أو معلمة أو قيمة مُعادة.

public record CreateUserRequest(
    @NotBlank
    String name,
    @NotBlank @Email @UniqueEmail
    String email
) {}

رسالة مخصصة مع الاستبدال

أشيروا إلى عناصر التعليق التوضيحي في الرسالة باستخدام {elementName}. واستخدموا ctx.buildConstraintViolationWithTemplate() لإضافة رسائل مخصصة تحتوي على بيانات ديناميكية.

@Constraint(validatedBy = RangeValidator.class)
public @interface InRange {
    int min() default 0;
    int max() default 100;
    String message() default "Must be between {min} and {max}";
    // ...
}

قيد على مستوى الفئة

طبّقوا قيدًا على مستوى الفئة للتحقق من عدة حقول معًا، وهو مفيد للقواعد التي تربط بين الحقول، مثل تأكيد كلمة المرور.

@Documented
@Constraint(validatedBy = PasswordMatchValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PasswordMatch {
    String message() default "Passwords do not match";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

تنفيذ المدقّق على مستوى الفئة

يتلقى المدقّق الكائن بأكمله. ويمكنه الوصول إلى عدة حقول لإجراء التحقق بينها.

public class PasswordMatchValidator implements ConstraintValidator<PasswordMatch, ChangePasswordRequest> {
    public boolean isValid(ChangePasswordRequest req, ConstraintValidatorContext ctx) {
        if (req.getNewPassword() == null) return true;
        boolean match = req.getNewPassword().equals(req.getConfirmPassword());
        if (!match) {
            ctx.disableDefaultConstraintViolation();
            ctx.buildConstraintViolationWithTemplate("Passwords do not match")
               .addPropertyNode("confirmPassword").addConstraintViolation();
        }
        return match;
    }
}

تركيب القيود

أنشئوا قيدًا مركبًا بإضافة القيود الموجودة إلى التعليق التوضيحي المخصص. وسيُطبَّق كلا القيدين تلقائيًا.

@NotBlank
@Email
@Size(max = 255)
@Constraint(validatedBy = {})
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidEmail {
    String message() default "Invalid email";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

إرجاع انتهاكات متعددة

استخدموا ctx.disableDefaultConstraintViolation() وأضيفوا رسائل انتهاك منفصلة لكل مشكلة يتم العثور عليها أثناء مرور واحد للمدقّق.

public boolean isValid(String password, ConstraintValidatorContext ctx) {
    List<String> issues = new ArrayList<>();
    if (password.length() < 8) issues.add("Too short");
    if (!password.matches(".*\\d.*")) issues.add("Must contain a digit");
    if (issues.isEmpty()) return true;
    ctx.disableDefaultConstraintViolation();
    issues.forEach(msg -> ctx.buildConstraintViolationWithTemplate(msg).addConstraintViolation());
    return false;
}

المدقّقات المُدارة بواسطة Spring

نظرًا إلى أن UniqueEmailValidator يحمل التعليق التوضيحي @Component، يحقن Spring المستودعات فيه. ولا يعمل ذلك إلا إذا جرى تشغيل المدقّق عبر مدقّق Spring، الذي يوصله Spring Boot تلقائيًا.

اختبار المدقّقات المخصصة

اختبروا المدقّقات مباشرةً على مستوى الوحدة، فلا حاجة إلى سياق Spring لمنطق التحقق الخالص. واستخدموا Validation.buildDefaultValidatorFactory() لاختبارات التكامل.

Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
CreateUserRequest req = new CreateUserRequest("", "bad-email", null);
Set<ConstraintViolation<CreateUserRequest>> violations = validator.validate(req);
System.out.println(violations.size()); // 3

تحقق سريع

ما الواجهة التي يطبّقها مدقّق القيد المخصص؟

مراجعة

أنشئوا @interface مع @Constraint(validatedBy=...). ونفّذوا ConstraintValidator. واستخدموا @Component لحقن Spring. تتحقق القيود على مستوى الفئة من عدة حقول معًا. وركّبوا القيود الموجودة لتجنب التكرار.

الأسئلة الشائعة

هل درس «تعليقات القيود المخصصة» مجاني؟

نعم — نص درس «تعليقات القيود المخصصة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.

ماذا ستتعلم في «تعليقات القيود المخصصة»؟

أنشئ تعليق @UniqueEmail مخصصًا مع تنفيذ ConstraintValidator تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟

لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «تعليقات القيود المخصصة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟

نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. التحقق من صحة الـ beans: ‏@NotNull و@Size و@Pattern
  2. تعليقات القيود المخصصة
  3. معالجة الاستثناءات العامة باستخدام @ControllerAdvice
  4. تفاصيل المشكلة وفق RFC 7807 واستجابات الأخطاء المتسقة
← العودة إلى Java Academy