Biznes mantiqida validatsiyani ko'rib chiqishning ham foydali, ham zararli tomonlari bor va Spring validatsiya (va ma'lumotlarni bog'lash) uchun loyihalash qoidalarini taklif qiladi, ular ikkisini ham inkor qilmaydi. Ayniqsa, validatsiya veb-darajaga bog'lanmasligi kerak, oson lokalizatsiya qilinishi kerak, shuningdek, har qanday mavjud validatorda ulanish imkoniyati bo'lishi kerak. Ushbu talablarni hisobga olgan holda, Spring Validator kontraktini taqdim etadi, bu asosiy va ilovaning har bir darajasida ishlatilishi mumkin.
Ma'lumotlarni bog'lash foydalanuvchi tomonidan kiritilgan ma'lumotlarni ilovaning domen modeli (yoki foydalanuvchi tomonidan kiritilgan ma'lumotlarni qayta ishlash uchun ishlatiladigan har qanday ob'ektlarga) dinamik ravishda bog'lashda foydalidir. Spring aynan shu vazifani bajarish uchun yaxshi shakllantirilgan DataBinder ni taqdim etadi. Validator va DataBinder asosan veb-darajada foydalaniladigan, ammo u bilan cheklanmagan validation paketini tashkil qiladi.
BeanWrapper Spring Framework-da asosiy tushunchadir va ko'p holatlarda ishlatiladi. Ammo, ehtimol, BeanWrapperni bevosita ishlatishga hojat qolmaydi. Biroq, bu qo'llab-quvvatlovchi hujjat ekanligi sababli, biz ba'zi izohlarni berishni lozim topdik. Ushbu bobda BeanWrapper ni qanday ishlatishni tushuntirib o'tamiz, chunki agar siz uni ishlatishni o'ylayotgan bo'lsangiz, ehtimol uni ma'lumotlarni ob'ektlarga bog'lash jarayonida qilasiz.
DataBinder va Springning past darajadagi BeanWrapper PropertyEditorSupport ni qiymatlarni tekshirish va formatlash uchun ishlatadi. JavaBeans klasslari spetsifikatsiyasining bir qismi bo'lgan PropertyEditor va PropertyEditorSupport turlari ham ushbu bobda tasvirlangan. Spring 3 da core.convert paketi paydo bo'ldi, u umumiy tur o'zgartirish vositalarini va foydalanuvchi interfeysi maydonlari qiymatlarini formatlash uchun yuqori darajadagi "format" paketini taqdim etadi. Siz PropertyEditorSupport ni amalga oshirishga oddiyroq alternativ sifatida ushbu paketlardan foydalanishingiz mumkin. Ular ham ushbu bobda tasvirlangan.
Spring Java Bean Validation ni moslashuvchan infrastrukturasi va Springning Validator kontraktiga adapter orqali qo'llab-quvvatlaydi. Ilovalar bir marta bean validatsiyasini global ravishda faollashtirishi va uni faqat validatsiya ehtiyojlari uchun ishlatishi mumkin. Veb-darajada, ilovalar DataBinder uchun Springning mahalliy Validator nusxalarini qo'shimcha ravishda ro'yxatdan o'tkazishi mumkin, bu maxsus validatsiya mantiqini ulamada foydali bo'lishi mumkin.
Spring Validator interfeysidan foydalanib validatsiya qilish
Spring Validator interfeysini taklif qiladi, bu ob'ektlarni validatsiya qilish uchun ishlatilishi mumkin. Validator interfeysi Errors ob'ekt bilan ishlaydi, shuning uchun validatatorlar dasturlarning haqiqiyligini tekshirishda aniqlangan barcha xatoliklarni Errors ob'ektiga xabar berishi mumkin.
Keling quyidagi kichik ma'lumot ob'ekti misolini ko'rib chiqaylik:
public class Person {
private String name;
private int age;
// oddiy getterlar va setterlar...
}
class Person(val name: String, val age: Int)
Quyidagi misol Person klassi uchun validatsiya mantiqini ta'minlaydi, org.springframework.validation.Validator interfeysining quyidagi ikki metodlarini amalga oshirish orqali:
-
supports(Class): BerilganClassnusxalarini validatsiya qilish mumkinmi buValidatortomonidan? -
validate(Object, org.springframework.validation.Errors): Belgilangan ob'ektni validatsiya qiladi va agar xatoliklar aniqlansa, belgilanganErrorsob'ektga ro'yxatga oladi.
Validator ni amalga oshirish juda oddiy, ayniqsa Spring Framework ham taqdim etadigan ValidationUtils yordamchi klassi haqida xabardor bo'lsangiz. Quyidagi misolda Person nusxalari uchun Validator amalga oshirilgan:
public class PersonValidator implements Validator {
/**
* Bu validatator faqat Person nusxalarini tekshiradi.
*/
public boolean supports(Class clazz) {
return Person.class.equals(clazz);
}
public void validate(Object obj, Errors e) {
ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
Person p = (Person) obj;
if (p.getAge() < 0) {
e.rejectValue("age", "negativevalue");
} else if (p.getAge() > 110) {
e.rejectValue("age", "too.darn.old");
}
}
}
class PersonValidator : Validator {
/**
* Bu validatator faqat Person nusxalarini tekshiradi.
*/
override fun supports(clazz: Class<*>): Boolean {
return Person::class.java == clazz
}
override fun validate(obj: Any, e: Errors) {
ValidationUtils.rejectIfEmpty(e, "name", "name.empty")
val p = obj as Person
if (p.age < 0) {
e.rejectValue("age", "negativevalue")
} else if (p.age > 110) {
e.rejectValue("age", "too.darn.old")
}
}
}
ValidationUtils klassining static rejectIfEmpty(..) metodi, agar name null yoki bo'sh qator bo'lsa, unda xususiyatni chiqarib tashlaydi. ValidationUtils ning javadocini ko'rib chiqing, u qanday funksiyalarni taqdim etadi, oldingi misolda ko'rsatilganlardan tashqari.
Albatta, siz har bir ichki ob'ektni validatsiya qilish uchun yagona to'liq Validator klassini amalga oshirishingiz mumkin, ammo ehtimol har bir ichki ob'ekt klassi uchun validatsiya mantiqini o'zida saqlaydigan o'z alohida Validator ni amalga oshirish yaxshiroq bo'ladi. Oddiy "to'liq funktsional" ob'ekt misoli Customer bo'lishi mumkin, u ikkita String (ism va familiya) va murakkab Address ob'ektni o'z ichiga oladi. Address ob'ektlaridan Customer ob'ektlaridan alohida foydalanish mumkin, shuning uchun alohida AddressValidator amalga oshirildi. Agar sizning CustomerValidator ni AddressValidator klassida mavjud bo'lgan mantiqni takrorlamasdan ishlatishni xohlasangiz, siz AddressValidator ga qaramlikni qo'shishingiz yoki uni o'zingizning CustomerValidator ichida yaratishingiz mumkin, quyidagi misolda ko'rsatilganidek:
public class CustomerValidator implements Validator {
private final Validator addressValidator;
public CustomerValidator(Validator addressValidator) {
if (addressValidator == null) {
throw new IllegalArgumentException("Berilgan [Validator] ta'minlanishi va null bo'lmasligi kerak.");
}
if (!addressValidator.supports(Address.class)) {
throw new IllegalArgumentException("Berilgan [Validator] [Address] nusxalarini validatsiya qilishni qo'llab-quvvatlashi kerak.");
}
this.addressValidator = addressValidator;
}
/**
* Bu validatator Customer nusxalarini, shuningdek barcha subklasslarini tekshiradi.
*/
public boolean supports(Class clazz) {
return Customer.class.isAssignableFrom(clazz);
}
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");
Customer customer = (Customer) target;
try {
errors.pushNestedPath("address");
ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);
} finally {
errors.popNestedPath();
}
}
}
class CustomerValidator(private val addressValidator: Validator) : Validator {
init {
if (addressValidator == null) {
throw IllegalArgumentException("Berilgan [Validator] ta'minlanishi va null bo'lmasligi kerak.")
}
if (!addressValidator.supports(Address::class.java)) {
throw IllegalArgumentException("Berilgan [Validator] [Address] nusxalarini validatsiya qilishni qo'llab-quvvatlashi kerak.")
}
}
/**
* Bu validatator Customer nusxalarini, shuningdek barcha subklasslarini tekshiradi.
*/
override fun supports(clazz: Class<>): Boolean {
return Customer::class.java.isAssignableFrom(clazz)
}
override fun validate(target: Any, errors: Errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required")
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required")
val customer = target as Customer
try {
errors.pushNestedPath("address")
ValidationUtils.invokeValidator(this.addressValidator, customer.address, errors)
} finally {
errors.popNestedPath()
}
}
}
Validatsiya xatolari validatatorga uzatilgan Errors ob'ektida qayd etiladi. Spring Web MVC da siz <spring:bind/> tegidan foydalanishingiz mumkin, lekin siz Errors ob'ekti bilan ham bevosita ishlashingiz mumkin. Uning taklif qiladigan metodlari haqida batafsil ma'lumot olish uchun, javadoc ga qarang.
Kodlarni xato xabarlariga almashtirish
Biz ma'lumotlar bog'lash va validatsiya haqida gaplashdik. Ushbu bo'lim validatsiya xatolariga mos keladigan xabarlarni chiqarishni muhokama qiladi. Oldingi bo'limda ko'rsatilgan misolda, biz name va age maydonlarini chiqarib tashladik. Agar biz MessageSource orqali xato xabarlarini chiqarishimiz kerak bo'lsa, biz ularni maydonni chiqarib tashlaganimizda qo'shgan xato kodini ishlatib chiqarishimiz mumkin ("name" va "age" aslida). Agar siz rejectValue yoki Errors interfeysining boshqa reject metodlaridan birini chaqirsangiz (to'g'ridan-to'g'ri yoki masalan ValidationUtils klassi orqali), asosiy amalga oshirish siz kiritgan kodni qayd etishdan tashqari bir qator qo'shimcha xato kodlarini ham qayd etadi. MessageCodesResolver interfeysi Errors interfeysi qayd etadigan xato kodlarini belgilaydi. Odatiy bo'lib DefaultMessageCodesResolver ishlatiladi, bu (masalan) siz kiritgan xato xabaridan tashqari, siz reject metodiga uzatilgan maydon nomini o'z ichiga olgan xato xabarlarini ham qayd etadi. Masalan, agar maydon rejectValue("age", "too.darn.old") orqali chiqarib tashlansa, Spring too.darn.old dan tashqari ham too.darn.old.age va too.darn.old.age.int kodlarini qayd etadi (birinchisi maydon nomini, ikkinchisi maydon turini o'z ichiga oladi). Bu xato xabarlarini ishlatishda ishlab chiqaruvchilar uchun qulaylik uchun qilingan.
MessageCodesResolver va odatiy strategiya haqida batafsil ma'lumot olish uchun, MessageCodesResolver va DefaultMessageCodesResolver javadoclariga qarang.
GO TO FULL VERSION