Spring Boot / الأساسي: التركيب وعقود HTTP / الدرس 5
التحقق وتفاصيل المشكلة الآمنة
افصل التحويل و Bean Validation وثوابت المجال وقيود الاستمرارية، واعرض خطأ مستقراً دون كشف القيم المرفوضة أو السبب الداخلي.
في هذه الصفحة
أهداف الدرس
- إعلان حد التحقق المطلوب وتفعيله.
- تحويل فشل MVC إلى مشكلة مستقرة.
- حفظ التفويض وفحص القاعدة كضابطين منفصلين.
قد ترفض حدود مختلفة الطلب نفسه
قد يفشل JSON أو تحويل النوع قبل وجود كائن طلب صالح. تفحص Bean Validation قيود القيمة المنشأة عندما يستدعيها التكامل، ويفرض المجال الانتقال وتحمي القاعدة الثوابت مع التزامن. تتكامل الطبقات وتحتاج أدلة تشخيص مميزة لا رسالة غير متوقعة عامة.
يستخدم Boot3.5 حزم Jakarta ويحتاج موفراً وتكاملاً مناسبين؛ أضف validation starter قصداً ولا تفترض أن web توفر كل شيء. ليست @Valid أمراً عاماً لكل كائن أينما كان؛ يحدد الحد والتعشيش والتوقيع والضبط المسار المنفذ فعلاً.
استخدم قيوداً تعبر عن المدخل المقبول
يفرض الجزء اسماً غير فارغ بحد ثمانين وسعراً صحيحاً موجباً بوحدة صغرى موثقة، ويضع @Valid على الجسم. قد يصبح المفقود الأولي صفراً قبل التحقق؛ فإذا وجب تمييزه من صفر مرسل استخدم مغلفاً مع NotNull. اختر التمثيل من العقد لا الراحة.
لا تجعل Size الاسم المكون من فراغ ذا معنى؛ فـ NotBlank قاعدة أخرى. ولا يثبت شكل البريد الملكية أو التفرد. قد تحتاج علاقة الحقول والحالة عملية مجال أو قيداً مخصصاً بفشل واضح. لا تنسب حدود الجسم وكلفة التحليل إلى annotation حقل واحدة.
package training.catalog;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.Size;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
record CreateProduct(@NotBlank @Size(max=80) String name,
@Positive int unitPriceCents) {}
// Methods shown as an MVC fragment inside a managed controller.
@PostMapping("/products")
ProductView create(@Valid @RequestBody CreateProduct request) {
return products.create(request);
}
يحتاج الجزء متحكماً وخدمة وموفر تحقق ونتيجة؛ وليس صنفاً مستقلاً قابلاً للتشغيل.
انشر حقول خطأ معتمدة لا الاستثناء الخام
تتيح ProblemDetail حالة وعنواناً وتفصيلاً وامتدادات مضبوطة. يحول الجزء فشل الجسم إلى 400 ويضم أزواج حقل ورمز دون القيمة المرفوضة أو نص الاستثناء الداخلي. لا يَعِد بترتيب الأخطاء؛ قارن المجموعة أو حدد فرزاً حتمياً إن لزم العقد.
يخص هذا المعالج MethodArgumentNotValidException؛ وقد تنتج تواقيع أخرى HandlerMethodValidationException، وتحتاج إخفاقات مرشحات الأمان معالجها. لا تدّع أن النصيحة تمسك كل النظام. افصل المجال والبنية بتحويل آمن واحتفظ بالسبب الأصلي في تشخيص مقيد.
package training.catalog;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
class ValidationAdvice {
@ExceptionHandler(MethodArgumentNotValidException.class)
ProblemDetail invalidBody(MethodArgumentNotValidException error) {
var problem = ProblemDetail.forStatusAndDetail(
HttpStatus.BAD_REQUEST, "Request validation failed.");
problem.setTitle("Invalid request");
problem.setProperty("errors", error.getBindingResult().getFieldErrors().stream()
.map(field -> Map.of("field", field.getField(),
"code", field.getCode() == null ? "invalid" : field.getCode()))
.toList());
return problem;
}
}
يحذف العقد المقصود القيم ويعالج عائلة محددة؛ ولم ينفذ HTTP أو إرسال النصيحة.
لا يفوض التحقق القرار ولا ينسق تزامنه
قد يخص معرف صحيح مستأجراً آخر، وتتجاوز كمية موجبة المخزون، ويتسابق طلبان صالحان على مفتاح فريد. افحص النطاق الموثوق واحم الانتقال وأبق القيود والمعاملة. لا تحول كل DataIntegrityViolationException إلى تكرار دون معرفة القيد والعملية.
تساعد رموز عامة مستقرة العميل دون تحليل نص استثناء. حدد التفصيل الآمن والترجمة ومعرفاً يربط بسجل مقيد. لا تضع كلمة مرور أو رمزاً أو سجلاً شخصياً أو بيئة كاملة في الرد لأن المدخل مرفوض؛ فالرفض لا يزيل حساسيته.
اختبر المقبول والمرفوض وثبات الحالة
اختبر JSON التالف والنوع والغياب والفراغ والحدود والتعشيش والتفويض. يفحص السالب عقد الخطأ وغياب تعديل جزئي ممنوع. لا يثبت باني DTO مباشر أن MVC يستدعي التحقق بالتوقيع والاعتماد المختارين.
اختر اختبار ويب محدوداً للربط والنصيحة، ووحدة لسياسة المجال، وتكامل قاعدة للثوابت المتزامنة عند السماح ببيئة مضبوطة. لا تُجهز قاعدة هنا وتبقى الأجزاء غير قابلة للتشغيل. سمِّ الصياغة المقبولة والسلوك المقصود والتنفيذ المرصود منفصلة ليبقى الدليل قابلاً للتقييم.
الأخطاء الشائعة وإصلاحها
وصل غير الصالح للخدمة.
- لماذا يحدث؟
- أُعلن التحقق ولم يفعل عند الحد.
- كيف تصلحه؟
- افحص الموفر وموضع Valid والتوقيع.
- كيف تتجنب تكراره؟
- اختبر رفض MVC محدوداً.
كشف رد المشكلة مدخلاً سرياً.
- لماذا يحدث؟
- سُلسلت القيمة أو الاستثناء الخام.
- كيف تصلحه؟
- أعد حقل ورمزاً معتمدين وقيد الدليل.
- كيف تتجنب تكراره؟
- اختبر علامة سر مصطنعة.
لم تمسك النصيحة 401.
- لماذا يحدث؟
- وقع الفشل بمرشح قبل MVC.
- كيف تصلحه؟
- اضبط معالج دخول ومنع الأمان المناسب.
- كيف تتجنب تكراره؟
- اختبر الحدين منفصلين.
اختبر فهمك
1. لماذا لا تميز Positive int الغائب من صفر مرسل؟
اعرض الحل المشروح
قد يتحول الغائب إلىصفر فيفشلان معاً. استخدم مغلفاً و NotNull إن لزم التمييز وحدد المجال بدلاً من افتراضي عرضي.
2. ما الناقص إذا مر اسم فراغي من حد الطول؟
اعرض الحل المشروح
لا يثبت الحد معنى غير فارغ. أضف القاعدة وحدد القص والتطبيع واختبر الحالتين، ولا تعد التحقق برهان هوية أو ملكية أوتفرد.
أهم ما تعلمته
- تختلف طبقات التحليل والتحقق والمجال والقيود.
- تكشف المشكلة عقداً مستقراً معتمداً.
- لا يثبت الإعلان تنفيذ التكامل.