Можно ли явно вызывать пользовательский валидатор из сервиса в Spring Boot? - PullRequest
0 голосов
/ 04 мая 2020

У меня есть собственный класс валидатора, который реализует Validator, например:

 public class MyCustomValidator implements Validator

Я хочу иметь возможность вызывать его метод validate() из Сервиса. Вот как выглядит этот метод:

@Override
public void validate(Object target, Errors errors) {
     // validation goes here
     MyClass request = (MyClass) target;
     if (request.getId() == null) {
         errors.reject("content.id", "Id is missing";
     }
}

Я не хочу иметь этот валидатор в моей конечной точке, потому что мне нужно выбрать объект для проверки из базы данных, а затем вызвать валидацию для него, поэтому мне нужно сделать это из моего сервиса.

Не могли бы вы подсказать мне, как этого добиться?

Ответы [ 3 ]

0 голосов
/ 04 мая 2020

Используйте аннотации валидации в классе, но не используйте @Valid в теле запроса, тогда Spring не проверит ваш класс.

public class MyClass{

   @NotNull
   private Integer id;

   @NotBlank
   private String data;
}

Сначала будет установлен автоматический проводной валидатор

@Autowired
private final Validator validator;

Затем для проверки класса с использованием валидатора условно при необходимости.

if(isValidate) {
    Set<ConstraintViolation<MyClass>> violations = validator.validate(myClassObj);
    if (!violations.isEmpty()) {
      throw new ConstraintViolationException(new HashSet<ConstraintViolation<?>>(violations));
    }

}
0 голосов
/ 04 мая 2020

Интерфейс Validator, насколько я понимаю, вызывается, как только сопоставляется объект (определяется методом public boolean Validator.supports(Class clazz)).

Однако, похоже, ваша цель состоит в проверке объекта MyClass только в определенное время c, переходящее с вашего уровня персистентности на уровень обслуживания.

Есть несколько способов достичь этого.

Первый и самый очевидный способ - не расширять любые классы, но использовать пользовательский компонент с некоторым понятием функции проверки:

@Component
public class CustomValidator{
    public void validate(MyClass target) throws ValidationException {
        // validation goes here
        if (target.getId() == null) {
             throw new ValidationException("Id is missing");
        }
    }
}

И внедрить / автоматически связать его с вашим сервисным объектом:

@Component
public class MyClassService{
    // will be injected in first instance of this component
    @Autowired
    private CustomValidator validator

    public MyClass get(MyClass target) {
        try {
             validator.validate(target);
             return dao.retrieve(target);
        } catch (ValidationException) {
             // handle validation error
        } catch (DataAccessException) {
             // handle dao exception
        }

    }
}

Это имеет то преимущество, что Вы сами можете контролировать валидацию и обработку ошибок. Отрицательной стороной является относительно высокий шаблон.

Однако, если вам нужны разные валидаторы для разных CRUD-операций (или методов обслуживания), вас может заинтересовать функция Spring Validation Groups .

Сначала вы создаете простой интерфейс маркера для каждой операции, которую вы хотите отличать:

interface OnCreate {};
interface OnUpdate {};

Затем все, что вам нужно сделать, это использовать интерфейсы маркера в полях вашего класса сущности. , используя аннотации Bean Validation :

public class MyClass{
    @Null(groups = OnCreate.class)
    @NotNull(groups = OnUpdate.class)
    String id;
}

Чтобы использовать эти группы в своем классе обслуживания, вам нужно будет использовать аннотацию @Validated.

@Validated
@Service
public class MyService {
    @Validated(OnCreate.class)
    void validateForCreate(@Valid InputWithGroups input){
      // do something
    }

    @Validated(OnUpdate.class)
    void validateForUpdate(@Valid InputWithGroups input){
      // do something
    }
}

Обратите внимание, что @Validated применяется как к классу обслуживания, так и к методам. Вы также можете установить группу для всего сервиса, если планируете использовать несколько сервисов.

Я на этот раз чаще всего использую встроенные аннотации Jakarta Bean Validation в сочетании с интерфейсами маркеров, из-за простоты использования и почти без шаблонов, при этом оставаясь несколько гибким и регулируемым.

0 голосов
/ 04 мая 2020

Вы можете ввести Validator и вызвать validate

@Autowired
Validator validator;

И затем вызвать validate:

Set<ConstraintViolation<Driver>> violations = validator.validate(yourObjectToValidate);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...