Статьи

Будьте стандартом, будьте свободны: используйте JSR-303 для валидации


Независимо от того, какой тип приложения мы разрабатываем, проверка кода является нашей повседневной задачей.
В течение многих лет мы использовали большое разнообразие методов и структур для успешной проверки. Тем не менее, когда-нибудь у нас был стандарт для Java для проверки,
спецификация Bean Validation (JSR-303) . Вопрос в следующем: стоит ли писать (или переписывать) наши проверки с использованием стандарта Bean Validation? Есть ли практическое преимущество в использовании JSR-303?

Сначала напишем валидатор (ограничение в номенклатуре Bean Validation), а затем воспользуемся им в нашем коде, чтобы увидеть, о чем мы говорим.

Создание ограничения JSR-303

Ограничение JSR-303 — это простая аннотация Java. Например, если мы хотим проверить ISBN, мы должны создать аннотацию @ISBN, например, следующую:

package org.openxava.books.constraints;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
import javax.validation.*;
import org.openxava.books.constraints.impl.*;

@Constraint(validatedBy = ISBNValidator.class) // ISBNValidator contains the validation logic
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
public @interface ISBN {

String message() default "{org.openxava.books.constraints.ISBN.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };

}

Ключевой частью здесь является аннотация @Constraint. Он помечает эту аннотацию как ограничение и указывает класс валидатора ISBNValidator, то есть класс с логикой валидации:

package org.openxava.books.constraints.impl;

import javax.validation.*;
import org.openxava.books.constraints.*;

public class ISBNValidator implements ConstraintValidator<ISBN, String> {

private static org.apache.commons.validator.ISBNValidator validator =
new org.apache.commons.validator.ISBNValidator(); // Validator from commons validator

public void initialize(ISBN isbn) {
}

public boolean isValid(String value, ConstraintValidatorContext ctx) { // The validation logic
if (value == null || value.trim().equals("")) return true;
return validator.isValid(value); // We simply delegate in commons validator
}

}

Валидатор должен реализовывать ConstraintValidator, поэтому он должен иметь методы initialize () и isValid (), последний содержит логику проверки. В этом случае мы просто делегируем валидатор из проекта Apache Commons Validator.
Как мы видим, создать валидатор довольно просто. Теперь, как мы можем использовать эту проверку в нашем приложении?

Использование валидатора

Спецификация JSR-303 говорит о том, как определять валидаторы, а не о том, как они используются и как они ведут себя в нашем приложении, это зависит от используемой нами среды. JPA2 и JSF2 имеют интеграцию Bean Validation, более того, многие современные фреймворки также поддерживают JSR-303. В этом случае мы собираемся разработать мини-приложение с использованием фреймворка OpenXava, которое использует вышеуказанное приложение @ISBN. Не паникуйте, разработка приложения OpenXava коротка (и приятна), поскольку нам нужно только написать классы предметной области.
После создания нового проекта OpenXava ( выполнения цели ant ) мы добавляем в него классы Author и Book.

Author.groovy:

package org.openxava.books.model

import javax.persistence.*
import org.openxava.model.*
import org.openxava.annotations.*

@Entity
class Author extends Identifiable {

@Required
String name

}

Book.groovy:

package org.openxava.books.model

import org.openxava.model.*;
import org.openxava.annotations.*;
import org.openxava.books.constraints.*;
import javax.persistence.*;

@Entity
class Book extends Identifiable {

@Required @Column(length=60)
String title

@ManyToOne(fetch=FetchType.LAZY)
@DescriptionsList
Author author

@Column(length=10)
@ISBN
String isbn

}

Хотя мы могли писать классы на Java, мы выбрали Groovy. Да, Groovy Web-разработка без Grails возможна. Однако важным моментом здесь является аннотация @ISBN в свойстве isbn. Нам не нужно больше работать, чтобы проверка работала. Если мы перейдем по адресу http: // localhost: 8080 / Books / modules / Book и попытаемся добавить книгу с неправильным ISBN, мы получим что-то вроде этого:

Как мы видим, использование проверки подлинности @ISBN в нашем приложении является полностью декларативной задачей, поэтому ее очень просто.

Почему я должен использовать Bean Validation?

Хотя JSR-303 прост в использовании и достаточно универсален для удовлетворения наших потребностей в валидации, на самом деле он не является чем-то впечатляющим и, возможно, не намного лучше, чем наша текущая среда валидации, поэтому зачем нам его использовать? Поскольку он поддерживается JPA2, JSF2, Spring Roo, Wicket, Tapestry и т. Д., А также должен быть включен в состав Java EE 6. Поэтому он дает нам больше свободы, поскольку наш код меньше зависит от среды приложения, в которой мы работаем. используя, таким образом, легче перенести наш код (по крайней мере, часть модели) из Wicket в Tapestry или из Spring Roo в OpenXava.

 

Используйте стандарт Bean Validation. Буть свободен!

Ресурсы