جلسه شماره 127رایگان

Spring MVC Validation | اعتبارسنجی در Spring MVC

00:32:17

توضیحات جلسه

🎥 این ویدیو قسمت صد و سیزدهم از بوت‌کمپ رایگان جاوا و دوازدهمین جلسه از پلی‌لیست تخصصی آموزش فریم‌ورک اسپرینگ است. 📚 در این جلسه از مسیر یادگیری Spring MVC سراغ یکی از حیاتی‌ترین مباحث توسعه وب می‌رویم: اعتبارسنجی داده‌ها و فرم‌ها (Validation) در Spring MVC. هنگام دریافت داده از کاربر، همیشه احتمال ورود اطلاعات ناقص، اشتباه یا حتی مخرب وجود دارد. در این ویدیو ابتدا صورت مسئله و خطرات عدم اعتبارسنجی را بررسی می‌کنیم و سپس روش‌های مختلف اعتبارسنجی در جاوا و اسپرینگ را گام‌به‌گام پیاده‌سازی می‌کنیم. یاد می‌گیریم چطور با استفاده از Java Bean Validation و انوتیشن‌های استاندارد، قوانین اعتبارسنجی را روی مدل‌ها تعریف کنیم، با کمک BindingResult خطاهای احتمالی را مدیریت کرده و در نهایت پیام‌های خطای مناسب را در لایه ویو به کاربر نمایش دهیم. در این جلسه یاد می‌گیریم: ⚙️ بررسی صورت مسئله و اهمیت اعتبارسنجی ورودی‌های کاربر در وب 🛠️ آشنایی با متدهای مختلف اعتبارسنجی داده‌ها در اسپرینگ 📋 مراحل گام‌به‌گام پیاده‌سازی استاندارد Validation در Spring MVC 🏷️ نحوه تعریف قوانین اعتبارسنجی روی فیلدها با انوتیشن‌ها (Declaring Validation) 🔗 مدیریت و اتصال خطاها در کنترلر با استفاده از BindingResult و کنترل جریان برنامه 🖥️ نمایش حرفه‌ای خطاهای اعتبارسنجی در فرم‌ها به کاربر (Displaying Error) 🧠 جمع‌بندی و مرور عمیق مفاهیم کلیدی جلسه اگر در حال یادگیری Spring Boot یا Spring MVC هستید، یادگیری اصولی Validation یکی از پایه‌ای‌ترین مهارت‌ها برای توسعه اپلیکیشن‌های مطمئن، امن و آماده ورود به بازار کار است. 📌 یوتیوب: https://youtube.com/@farzadafi 📌 آپارات: https://aparat.com/farzadafi 📌 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi 🌐 وب‌سایت: https://farzadafi.ir هر سوالی داشته باشید می‌توانید در گروه بپرسید تا من یا مربی‌های گروه کمکتان کنیم 💬 🎯 بوت‌کمپ رایگان جاوا – آموزش کاملاً پروژه‌محور برای یادگیری عمیق جاوا و ورود به بازار کار.

جزوه و مستندات

مفاهیم کلیدی

  • Jakarta Validation API

مشخصه و استاندارد رسمی در اکوسیستم جاوا (شناخته‌شده با نام JSR 303) جهت اعتبارسنجی اعلانی داده‌ها روی فیلدهای مدل به کمک انوتیشن‌ها، به جای پیاده‌سازی بلوک‌های شرطی تکراری.

  • Hibernate Validator

پیاده‌سازی مرجع استاندارد Jakarta Validation که علاوه بر قواعد پایه استاندارد، مجموعه‌ای اختصاصی از قیود کاربردی نظیر فرمت کارت‌های اعتباری، بارکدها و آدرس‌های اینترنتی را فراهم می‌کند.

  • spring-boot-starter-validation

استارتر اختصاصی Spring Boot جهت اتصال موتور اعتبارسنجی؛ از نسخه 2.3 به بعد دیگر در استارتر وب گنجانده نشده و باید به طور مستقل به فایل مدیریت وابستگی پروژه افزوده شود.

  • @Null

بررسی می‌کند که مقدار عنصر حتماً برابر با null باشد.

  • @NotNull

تضمین می‌کند که مقدار ارجاع داده‌شده برابر با null نباشد؛ با این حال رشته خالی یا کالکشن بدون عضو را معتبر در نظر می‌گیرد.

  • @NotEmpty

علاوه بر بررسی عدم برابری با null، تضمین می‌کند که اندازه آرایه، کالکشن، مپ یا طول رشته بزرگ‌تر از صفر باشد.

  • @NotBlank

مختص متغیرهای متنی که تضمین می‌کند مقدار رشته نه null باشد و نه صرفاً از کاراکترهای فضای خالی تشکیل شده باشد (طول رشته پس از حذف فاصله‌ها باید بیشتر از صفر باشد).

  • @AssertTrue

بررسی می‌کند که فیلد منطقی از نوع boolean یا Boolean حتماً دارای مقدار true باشد.

  • @AssertFalse

بررسی می‌کند که فیلد منطقی از نوع boolean یا Boolean حتماً دارای مقدار false باشد.

  • @Min

تضمین می‌کند که مقدار عددی یا رشته‌ای قابل تبدیل به عدد، بزرگ‌تر یا مساوی با حداقل مقدار تعیین‌شده باشد.

  • @Max

تضمین می‌کند که مقدار عددی یا رشته‌ای قابل تبدیل به عدد، کوچک‌تر یا مساوی با حداکثر مقدار تعیین‌شده باشد.

  • @DecimalMin

بررسی می‌کند که مقدار عددی، بزرگ‌تر یا مساوی با مقدار تعیین‌شده به صورت رشته‌ای باشد؛ پارامتر inclusive امکان تعیین شمول یا عدم شمول مساوی را فراهم می‌کند.

  • @DecimalMax

بررسی می‌کند که مقدار عددی، کوچک‌تر یا مساوی با مقدار تعیین‌شده به صورت رشته‌ای باشد؛ پارامتر inclusive امکان تعیین شمول یا عدم شمول مساوی را فراهم می‌کند.

  • @Positive

بررسی می‌کند که مقدار عددی کاملاً مثبت و بزرگ‌تر از صفر باشد.

  • @PositiveOrZero

بررسی می‌کند که مقدار عددی مثبت یا دقیقاً مساوی صفر باشد.

  • @Negative

بررسی می‌کند که مقدار عددی کاملاً منفی و کوچک‌تر از صفر باشد.

  • @NegativeOrZero

بررسی می‌کند که مقدار عددی منفی یا مساوی صفر باشد.

  • @Digits

بررسی می‌کند که ساختار عددی حداکثر دارای تعداد مشخصی از ارقام در بخش صحیح (integer) و بخش اعشار (fraction) باشد.

  • @Size

محدود کردن اندازه طول رشته‌ها، اعضای کالکشن‌ها، مپ‌ها و آرایه‌ها در بازه بسته حداقل (min) و حداکثر (max).

  • @Pattern

انطباق دقیق مقدار متنی با یک عبارت منظم (Regex) به همراه پرچم‌های تطبیق اختیاری.

  • @Email

بررسی صحت ساختار آدرس ایمیل در توالی کاراکترها بر اساس استانداردهای متنی.

  • @Past

تضمین می‌کند که مقدار زمانی یا تقویمی حتماً تاریخی در گذشته باشد.

  • @PastOrPresent

بررسی می‌کند که مقدار زمانی مشخص‌شده در گذشته یا هم‌زمان با لحظه جاری باشد.

  • @Future

تضمین می‌کند که مقدار زمانی یا تقویمی حتماً تاریخی در آینده باشد.

  • @FutureOrPresent

بررسی می‌کند که مقدار زمانی مشخص‌شده در آینده یا هم‌زمان با لحظه جاری باشد.

  • @CreditCardNumber

انوتیشن اختصاصی Hibernate Validator جهت اعتبارسنجی صحت شماره کارت بانکی بر اساس الگوریتم چک‌سام فرمول Luhn برای ممانعت از خطاهای تایپی.

  • @Currency

بررسی تطابق واحد پولی یک شیء MonetaryAmount با لیست واحدهای ارزی مجاز تعریف‌شده.

  • @DurationMin

بررسی می‌کند که مقدار مدت‌زمان در ساختار Duration از حداقل زمان تعریف‌شده کمتر نباشد.

  • @DurationMax

بررسی می‌کند که مقدار مدت‌زمان در ساختار Duration از حداکثر زمان تعریف‌شده بیشتر نباشد.

  • @EAN

بررسی اعتبار توالی کاراکترها به عنوان یک بارکد استاندارد نظیر EAN-13.

  • @IpAddress

بررسی صحت ساختار آدرس شبکه و اطمینان از فرمت معتبر IPv4 یا IPv6.

  • @ISBN

بررسی صحت شناسه استاندارد بین‌المللی کتاب با پشتیبانی از ساختارهای ده‌رقمی یا سیزده‌رقمی.

  • @Length

انوتیشن اختصاصی Hibernate Validator برای بررسی طول رشته متنی در بازه مشخص حداقل و حداکثر.

  • @CodePointLength

بررسی طول رشته متنی بر اساس تعداد کاراکترهای یونیکد (Code Points) به همراه استراتژی نرمال‌سازی.

  • @LuhnCheck

اجرای مستقیم الگوریتم بررسی مجموع ارقام لوهن روی بخشی از رشته متنی با تعیین اندیس‌های شروع، پایان و رقم کنترلی.

  • @Mod10Check

اجرای الگوریتم اعتبارسنجی رقم کنترلی بر پایه محاسبات باقی‌مانده تقسیم بر 10 با اعمال وزن‌ها و ضرایب سفارشی.

  • @Mod11Check

اجرای الگوریتم اعتبارسنجی رقم کنترلی بر پایه محاسبات باقی‌مانده تقسیم بر 11 با امکان تعریف آستانه رشد ضرایب.

  • @Normalized

بررسی این موضوع که رشته متنی بر اساس یکی از فرم‌های استاندارد یونیکد نرمال‌سازی شده باشد.

  • @Range

بررسی قرار داشتن یک مقدار عددی یا رشته متنی عددی در یک محدوده مشخص حداقل و حداکثر.

  • @ScriptAssert

انوتیشن اختصاصی در سطح کلاس (Class-Level) که با استفاده از موتورهای اسکریپت‌نویسی استاندارد جاوا (JSR 223) منطق اعتبارسنجی پیچیده میان چندین فیلد هم‌زمان را بررسی می‌کند.

  • @UniqueElements

بررسی می‌کند که تمام عناصر موجود در یک کالکشن بر اساس متد equals() کاملاً یکتا و فاقد عضو تکراری باشند.

  • @URL

اعتبارسنجی آدرس اینترنتی بر پایه مشخصات استاندارد RFC 2396 با قابلیت کنترل پروتکل، میزبان و پورت.

  • @UUID

بررسی اعتبار قالب شناسه منحصر‌به‌فرد جهانی مطابق استاندارد RFC 4122 با تنظیمات اختصاصی نسخه و فرمت حروف.

  • @BitcoinAddress

بررسی صحت ساختار آدرس شبکه بیت‌کوین بر اساس انواع استانداردهای مجاز شبکه رمزارز.

  • @CNPJ

بررسی شماره ثبت شرکت‌ها و اشخاص حقوقی کشور برزیل.

  • @CPF

بررسی کد ملی و شناسه مالیاتی اشخاص حقیقی کشور برزیل.

  • @TituloEleitoral

اعتبارسنجی شماره کارت رأی‌دهندگان کشور برزیل.

  • @NIP

اعتبارسنجی شماره شناسایی مالیات بر ارزش افزوده کشور لهستان.

  • @PESEL

بررسی شماره شناسایی ملی شهروندان کشور لهستان.

  • @REGON

اعتبارسنجی شناسه ملی ثبت تجاری اشخاص حقوقی در لهستان با پشتیبانی از ارقام 9 و 14 رقمی.

  • @INN

بررسی شماره شناسایی مالیات‌دهندگان کشور روسیه برای اشخاص حقیقی و حقوقی.

  • @KorRRN

اعتبارسنجی شماره ثبت هویت مقیمین کشور کره جنوبی.

  • @Valid

انوتیشن استاندارد در امضای متدهای کنترلر جهت صدور فرمان اجرای فرایند ارزیابی قیود مدل، پس از اتصال داده‌ها و قبل از اجرای بدنه متد.

  • Errors

اینترفیس اختصاصی فریم‌ورک اسپرینگ جهت جمع‌آوری، ردگیری و گزارش خطاهای ناشی از بایندینگ و اعتبارسنجی در کنترلر.

موارد مصاحبه ای

  • تفاوت دقیق عملکردی میان سه انوتیشن @NotNull، @NotEmpty و @NotBlank چیست؟

انوتیشن @NotNull صرفاً عدم اشاره به null را بررسی می‌کند و رشته‌های خالی را معتبر می‌داند؛ @NotEmpty علاوه بر رد null، بررسی می‌کند طول رشته یا کالکشن بزرگ‌تر از صفر باشد اما فضاهای خالی را می‌پذیرد؛ @NotBlank انحصاری رشته‌هاست و مقدار را trim کرده و وجود حداقل یک کاراکتر معتبر غیر از فاصله را الزامی می‌سازد.

  • تغییر شیوه مدیریت وابستگی اعتبارسنجی از نسخه 2.3 فریم‌ورک Spring Boot به بعد چه بود؟

تا قبل از نسخه 2.3، ابزار اعتبارسنجی به صورت درون‌ساخت در پکیج spring-boot-starter-web وجود داشت؛ اما از نسخه 2.3 به بعد، ماژول اعتبارسنجی تفکیک شد و نیازمند افزودن مستقیم spring-boot-starter-validation به فایل تنظیمات بیلد است.

  • محدودیت انوتیشن‌های استاندارد Jakarta Validation در مقایسه با انوتیشن‌های Hibernate Validator از نظر سطح تعریف چیست؟

تمامی قیود تعریف‌شده در استاندارد Jakarta Validation صرفاً در سطح فیلد یا متد اعمال می‌شوند؛ در حالی که Hibernate Validator انوتیشن‌هایی نظیر @ScriptAssert را برای اعمال اعتبارسنجی‌های چندفیلدی در سطح کلاس فراهم کرده است.

  • قانون الزامی در ترتیب قرارگیری پارامتر Errors در کنترلرهای Spring MVC چیست؟

پارامتر Errors (یا همتای آن BindingResult) الزاماً باید بلافاصله پس از آرگومان مدل نشانه‌گذاری‌شده با @Valid در امضای متد قرار گیرد، در غیر این صورت فریم‌ورک به جای بایند کردن خطاها، اکسپشن پرتاب می‌کند.

  • آیا موفقیت در اعتبارسنجی @CreditCardNumber به معنای فعال بودن و قابلیت شارژ حساب کارت است؟

خیر؛ این انوتیشن فقط صحت الگوریتم ریاضی فرمول Luhn را برای ممانعت از خطاهای تایپی می‌سنجد و هیچ استعلامی از حساب بانکی، موجودی یا اتصال کارت به درگاه پرداخت به عمل نمی‌آورد.

  • کدام انوتیشن‌های اعتبارسنجی روی ساختار DDL و جدول دیتابیس در Hibernate تأثیرگذار هستند؟

انوتیشن @NotNull ستون را معادل not null قرار می‌دهد؛ انوتیشن‌های @Size و @Length طول ستون را معادل مقدار ماکزیمم ست می‌کنند؛ انوتیشن @Digits برای تعیین دقت و مقیاس ستون عددی استفاده می‌شود و @Min و @Max قید check constraint به ساختار جدول دیتابیس اضافه می‌کنند.

سناریو کاربردی

  • اعتبارسنجی اعلانی مدل داده و مدیریت پاسخ در متد کنترلر

در این سناریو، فیلدهای سفارش از جمله نام، ترکیبات، اطلاعات پرداخت و قالب‌های متنی بر اساس قیود استاندارد اعتبارسنجی شده و در صورت نقض هر قید، کنترلر از ادامه پردازش ممانعت کرده و کاربر را با خطاهای مربوطه به فرم بازمی‌گرداند:

۱. تعریف قیود اعتبارسنجی روی کلاس مدل:

@Data
public class TacoOrder {

    @NotBlank(message = "Delivery name is required")
    private String deliveryName;

    @NotBlank(message = "Street is required")
    private String deliveryStreet;

    @CreditCardNumber(message = "Not a valid credit card number")
    private String ccNumber;

    @Pattern(regexp = "^(0[1-9]|1[0-2])([\\/])([2-9][0-9])$", message = "Must be formatted MM/YY")
    private String ccExpiration;

    @Digits(integer = 3, fraction = 0, message = "Invalid CVV")
    private String ccCVV;

    @NotNull
    @Size(min = 1, message = "You must choose at least 1 ingredient")
    private List<Ingredient> ingredients = new ArrayList<>();
}

۲. بررسی خطاهای اعتبارسنجی در متد لایه کنترلر:

@Slf4j
@Controller
@RequestMapping("/orders")
public class OrderController {

    @PostMapping
    public String processOrder(@Valid TacoOrder order, Errors errors) {
        if (errors.hasErrors()) {
            log.warn("Validation failed for submitted order: {}", errors.getAllErrors());
            return "orderForm";
        }

        log.info("Order processed successfully: {}", order);
        return "redirect:/";
    }
}

در صورتی که هر یک از قیود نقض شود، متد errors.hasErrors() مقدار true برمی‌گرداند و به جای پردازش منطق تجاری یا ذخیره‌سازی، جریان کنترل دوباره به فایل نمای مربوطه ارجاع داده می‌شود تا پیام‌های خطا بر اساس ویژگی message به کاربر نمایش داده شوند.

بیشتر بدانید

  • ویژگی‌های مشترک در تمام قیود اعتبارسنجی

مطابق مشخصه Jakarta Validation، هر انوتیشن اعتبارسنجی به طور پیش‌فرض دارای سه پارامتر اساسی شامل message (پیام نمایش داده‌شده به کاربر هنگام نقض قید)، groups (دسته‌بندی و مرحله‌بندی اعتبارسنجی) و payload (حمل داده‌های فراداده‌ای اضافه به سمت سیستم پردازش خطا) است.

  • مکانیزم الگوریتم لوهن در اعتبارسنجی داده‌ها

فرمول ریاضی لوهن بر پایه محاسبات مجموع ارقام با اعمال ضرایب متناوب کار می‌کند و یک ابزار اعتبارسنجی ارزان‌قیمت از نظر بار محاسباتی است که بدون نیاز به برقراری ارتباط شبکه، بخش عمده‌ای از اشتباهات سهوی کاربر را در ورود شماره کارت شناسایی می‌کند.

  • پشتیبانی بومی از تایپ‌های زمانی جاوا 8

انوتیشن‌های زمانی از جمله @Past و @Future کلاس‌های قدیمی نظیر Date و همچنین کلاس‌های مدرن بسته java.time مثل LocalDate، LocalDateTime، Instant و YearMonth را بدون نیاز به مبدل اضافی پشتیبانی می‌کنند.