Java Web Uygulamalarında Doğrulama Yöntemleri
Bean Validation
Standart Java doğrulama spesifikasyonu
Ek Açıklama bazlı çalışan bir mekanizma
Alan, metot, parametre ölçeğinde kısıtlar sağlıyor
Java SE/EE versiyonları ile çalışabiliyor
Bean Validation
Ek Açıklamaların üstveriyi ezme/miras alma imkanı var
Kısıtlamaya çalıştığımız problemler (çoğunlukla) öntanımlı
Yeniden kullanılabilir: aynı ihtiyaç için birden fazla özel kısıt yazmak verimsiz
Doğrulamayı veritabanına bırakmak daha maliyetli, hataları idame etmek zor
Bean Validation 1.0
JSR 303
Java EE 6
2009
İlk obje doğrulama standardı
Özellik ve "bean" seviyesinde doğrulama
Özel doğrulayıcı yazılabiliyor
Hazır i18n desteği
Bean Validation 1.1
JSR 349
Java EE 7
2013
Metot seviyesinde doğrulama (parametre, dönüş değerleri)
Bağımlılık enjeksiyonu desteği
CDI entegrasyonu
EL ile hata mesajlarını yönetebilme
Bean Validation 2.0
JSR 380
Java EE 8
2017
Parametre içinde ek açıklama kullanımı
JavaFX desteği
Tarih değişkenleri
Hibernate Validator
Referans implementasyon
Apache 2.0
Ek özellikler sunuyor
Programa dayalı kısıt tanımları
Ek Açıklama işleyici
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>
Ek Açıklama İşleyici
Derleyici ile etkileşen bir mekanizma
Ek Açıklama hatalı biçimde kullanılırsa hata fırlatıyor.
Çeşitli kriterleri derlenme zamanında kontrol ediyor:
Sadece izin verilen tiplerde kullanılabilir.
Statik alanlarda kullanılamaz.
İlkel tiplerde @Valid kullanılamaz.
Parametre değerleri geçerli olmalıdır.
Üstveri
Alanlar, metotlar, ek açıklamalar
Doğrulanacak her obje için üstveriye ihtiyaç var
Üstveri uygulama başlatılırken alınıyor, amaç maliyet azaltmak
javax.validation.metadata altında tanımlı
Bu paket ile üstveriye ait özelliklere ulaşabiliyoruz.
Kullanım
Alan seviyesinde kullanım
public class User {
@NotNull
private String username;
@Email(message = "Email must be valid")
private String email;
@Min(value = 18)
@Max(value = 100)
private int age;
@Size(min = 8, max = 42)
private String password;
}
Metot seviyesinde kullanım
@AssertTrue
public boolean isVerified() {
...
}
@NotNull
public String getUsername() {
...
}
Parametre seviyesinde kullanım
List<@Positive Integer> ageList;
Map<@Currency MonetaryAmount, @Positive BigDecimal> values;
Cat(@NotNull name) {
}
Sınıf seviyesinde kullanım
@PasswordMatches
public class User {
...
}
Özel Ek Açıklama Yazımı - 1
@Target({ METHOD, FIELD, TYPE, PARAMETER, CONSTRUCTOR})
@Retention(RUNTIME)
@Constraint(validatedBy = {PasswordValidator.class})
public @interface PasswordMatches {
String message() default "Passwords must match.";
Class<?>[] groups() default { };
}
Özel Ek Açıklama Yazımı - 2
public class PasswordValidator implements ConstraintValidator<PasswordMatches, Object> {
...
@Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
//Wrap object to type
return o.getPassword().equals(o.getMatchingPassword());
}
XML ile Kısıt Tanımı
<?xml version="1.0" encoding="UTF-8"?>
<validation-config
xmlns="http://xmlns.jcp.org/xml/ns/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/validation/configuration validation-configuration-2.0.xsd"
version="2.0">
<bean class="User">
<field name="username">
<constraint annotation="javax.validation.constraints.NotNull"/>
</field>
<field name="password">
<constraint annotation="javax.validation.constraints.Min">
<element name="value">8</element>
</constraint>
</field>
</validation-config>
İfade Dili Kullanımı
@NotEmpty(message = "{common.not_empty}")
private String name;
@Size(min = 10, message = "Description '${validatedValue}' must be at least {min}" +
" characters. Current length: '${validatedValue.length()}'")
private String description;
Programa Dayalı Kısıt Tanımları
Standard, XML ve ek açıklama bazlı kısıtlara izin veriyor.
Hibernate Validator programa dayalı kısıt uygulayabilmeyi de sağlıyor.
HibernateValidatorConfiguration config = Validation
.byProvider(HibernateValidator.class)
.configure();
ConstraintMapping mapping = config.createConstraintMapping();
mapping
.type(User.class)
.property("username", FIELD)
.constraint(new NotNullDef())
.property("password", FIELD)
.ignoreAnnotations(true)
.constraint(new NotNullDef())
.constraint(new SizeDef().min(8).max(42));
Validator validator = config.addMapping(mapping)
.buildValidatorFactory()
.getValidator();
JSF ile Doğrulama
<h:inputText id="email" value="#{user.username}" validatorMessage="Username can only contain letters numbers, dashes, underscores.">
<f:validateRegex pattern="^[a-zA-Z0-9._-]{3,}$"/>
</h:inputText>
<h:inputSecret id="password" value="#{user.password}" validatorMessage="Password must contain at least 8 characters.">
<f:validateLength minimum="8" maximum="42"/>
</h:inputSecret>
<h:inputText id="age" value="#{user.age}" validatorMessage="You must be at least 18 years old.">
<f:validateLongRange minimum="18" maximum="100"/>
</h:inputText>