2015-02-24 4 views
11

Аннотированная проверка весов в полях POJO работает, когда она создана из тела запроса json. Однако, когда я создаю один и тот же объект вручную (используя сеттеры) и хочу инициировать проверку, я не уверен, как это сделать.Как вручную запустить проверку весны?

Вот класс регистрации, в котором есть внутренний класс Builder, который может построить объект. В методе построения я хотел бы активировать проверку весны. Прокрутите страницу вниз и проверьте методы Builder.build() и Builder.valiate(), чтобы увидеть текущую реализацию. Я использую javax.validation.Validator для запуска проверки, но, по возможности, предпочитаю использовать весеннюю проверку.

package com.projcore.dao; 

import com.projcore.util.ToString; 
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 
import org.hibernate.validator.constraints.NotEmpty; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import javax.validation.ConstraintViolation; 
import javax.validation.Valid; 
import javax.validation.Validation; 
import javax.validation.Validator; 
import javax.validation.constraints.Size; 
import java.util.List; 
import java.util.Set; 

/** 
* The data transfer object that contains the information of a Registration 
* and validation rules for attributes. 
*/ 
@JsonIgnoreProperties(ignoreUnknown = true) 
public final class Registration { 
    private static final Logger LOGGER = LoggerFactory.getLogger(Registration.class); 

    private String id; 

    @NotEmpty 
    @Size(max = 255) 
    private String messageId; 

    @NotEmpty 
    @Size(max = 255) 
    private String version; 

    @Size(max = 255) 
    private String system; 

    public Registration() { 
    } 

    private Registration(Builder builder) { 
     this.id = builder.id; 
     this.messageId = builder.messageId; 
     this.version = builder.version; 
     this.system = builder.system; 
    } 

    public static Builder getBuilder() { 
     return new Builder(); 
    } 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getMessageId() { 
     return messageId; 
    } 

    public void setMessageId(String messageId) { 
     this.messageId = messageId; 
    } 

    public String getVersion() { 
     return version; 
    } 

    public void setVersion(String version) { 
     this.version = version; 
    } 

    public String getSystem() { 
     return system; 
    } 

    public void setSystem(String system) { 
     this.system = system; 
    } 

    @Override 
    public String toString() { 
     return ToString.create(this); 
    } 

    /** 
    * Builder pattern makes the object easier to construct in one line. 
    */ 
    public static class Builder { 

     private String id; 

     private String messageId; 

     private String version; 

     private String system; 

     private Builder() {} 

     public Builder id(String id) { 
      this.id = id; 
      return this; 
     } 

     public Builder messageId(String messageId) { 
      this.messageId = messageId; 
      return this; 
     } 


     public Builder version(String version) { 
      this.version = version; 
      return this; 
     } 

     public Builder system(String system) { 
      this.system = system; 
      return this; 
     } 

     public Registration build() { 
      Registration entry = new Registration(this); 

      // *** Would like to trigger spring validation here *** 
      Set violations = validate(entry); 
      if (violations.isEmpty()) 
       return entry; 
      else 
       throw new RuntimeException(violations.toString()); 
     } 

     private Set validate(Registration entry) { 
      Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); 
      Set<ConstraintViolation<Registration>> constraintViolations = validator.validate(entry); 
      return constraintViolations; 
     } 

    } 
} 

Validation прекрасно работает здесь:

@RequestMapping(method = RequestMethod.POST) 
@ResponseStatus(HttpStatus.CREATED) 
Registration create(@RequestBody @Valid Registration registration) 

Решение:

Удалены Registraion.Builder.validate(). Обновлено Registraion.Builder.build() для:

public Registration build() { 
     Registration entry = new Registration(this); 
     return (Registration) ValidatorUtil.validate(entry); 
    } 

ValidationUtil.java

package projcore.util; 

import com.ericsson.admcore.error.InvalidDataException; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.stereotype.Service; 
import org.springframework.validation.BeanPropertyBindingResult; 
import org.springframework.validation.Errors; 
import org.springframework.validation.beanvalidation.SpringValidatorAdapter; 

import javax.validation.Validation; 
import javax.validation.Validator; 
import java.util.Set; 

public class ValidatorUtil { 
    private static final Logger LOGGER = LoggerFactory.getLogger(ValidatorUtil.class); 
    private static final Validator javaxValidator = Validation.buildDefaultValidatorFactory().getValidator(); 
    private static final SpringValidatorAdapter validator = new SpringValidatorAdapter(javaxValidator); 

    public static Object validate(Object entry) { 
     Errors errors = new BeanPropertyBindingResult(entry, entry.getClass().getName()); 
     validator.validate(entry, errors); 
     if (errors == null || errors.getAllErrors().isEmpty()) 
      return entry; 
     else { 
      LOGGER.error(errors.toString()); 
      throw new InvalidDataException(errors.getAllErrors().toString(), errors); 
     } 
    } 
} 

InvalidDataException.java

package projcore.error; 

import org.springframework.validation.Errors; 

/** 
* This exception is thrown when the dao has invalid data. 
*/ 
public class InvalidDataException extends RuntimeException { 
    private Errors errors; 

    public InvalidDataException(String msg, Errors errors) { 
     super(msg); 
     setErrors(errors); 
    } 

    public Errors getErrors() { 
     return errors; 
    } 

    public void setErrors(Errors errors) { 
     this.errors = errors; 
    } 
} 

ответ

14

Spring обеспечивает полную поддержку JSR-303 Bean Validation API. Это включает удобную поддержку для начальной загрузки реализации JSR-303 в качестве компонента Spring. Это позволяет вводить javax.validation.Validator везде, где требуется проверка в приложении.

Используйте LocalValidatorFactoryBean для настройки по умолчанию JSR-303 в качестве средства проверки Spring фасоли:

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" /> 

Базовая конфигурация выше, будет вызывать JSR-303, чтобы инициализировать, используя свой механизм начальной загрузки по умолчанию. Ожидается, что поставщик JSR-303, такой как Hibernate Validator, будет присутствовать в пути к классам и будет обнаружен автоматически.

5.7.2.1 Инъекционного валидатор

LocalValidatorFactoryBean implements both javax.validation.Validator and org.springframework.validation.Validator. Вы можете вводить ссылку на один из этих двух интерфейсов в бобы, которые должны вызвать логику проверки.

Вводите ссылку на javax.validation.Validator, если вы предпочитаете работать с JSR-303 API непосредственно:

// JSR-303 Validator 
import javax.validation.Validator; 

@Service 
public class MyService { 

    @Autowired 
    private Validator validator; 

} 

впрыснуть ссылку на org.springframework.validation.Validator, если ваш боб требует Spring Validation API:

// Spring Validator 
import org.springframework.validation.Validator; 

@Service 
public class MyService { 

    @Autowired 
    private Validator validator; 

} 

Ниже приводится пример хорошо выраженного примера Using JSR 303 with "classic" Spring Validators (enter the SpringValidatorAdapter)

Эта ссылка очень полезна. Обертка javax.validation.Validator в org.springframework.validation.beanvalidation.SpringValidatorAdapter помогла справиться с ошибками последовательно.Вы можете добавить это как ответ, так , что я могу принять это

и Spring doc here

+2

Я думаю, что Spring Загрузочный также предусматривает, что валидатор боб для вас (не то, что это трудно сделать самостоятельно). –

+1

Означает ли это, что весенний валидатор может использоваться только в классе @Service для запуска проверки? Я сделал достаточно чтения в Интернете, поэтому видел такие примеры, но я до сих пор не понимаю, как я могу это сделать в рамках POJO, следовательно, вопрос. Я также знаю, как инициировать проверку для пользовательского валидатора, но не как инициировать проверку по умолчанию в POJO. Если возможно, можете ли вы дать конкретный ответ в контексте того, что у меня есть. –

+1

Вы можете вводить валидатор в любой весенний боб. есть старый пример здесь http://nonrepeatable.blogspot.com/2010/04/using-jsr-303-with-classic-spring.html. комментарий здесь, если у вас все еще есть проблемы – iamiddy

Смежные вопросы