Spring Validation

손쉽게 annotation을 붙여서 Validation을 수행할 수 있게 도와준다. 또한 validation 로직을 여러 레이어에서 중복되지 않고 하나의 도메인 모델에서 한꺼번에 처리할 수 있도록 도와준다.

사전 지식

사용법

  1. hibernate validator 의존성 추가
    <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-validator</artifactId>
     <version>5.4.0.Final</version>
    </dependency>
    
  2. Bean 추가
    @Configuration
    public class AppConfig {
     @Bean
     public LocalValidatorFactoryBean validator() {
       return new LocalValidatorFactoryBean();
     }
    }
    
  3. 도메인 모델에 @Constraints 관련 어노테이션 추가

    @Data
    public class Message {
     // 이 NotNull처럼 `javax.validation.Constraint` 어노테이션이 붙어있는 어노테이션들
     // `javax.validation.constraints` 패키지를 보면 됨.
     @NotNull
     private String sender;
    
     private String message
    }
    
  4. Validator @Autowired 끌어와서 체크 후 처리. javax.validation.Validator 와 스프링 버전이 있는데 특별한 기능이 필요 없으면 그냥 javax 아래에 있는 것을 사용하면 됨

    @RestController
    @RequestMapping("/messages")
    public class MessageController {
     private final Validator validator;
    
     @Autowired
     public MessageController(Validator validator) {
         this.validator = validator;
     }
    
     @PostMapping
     public Map<String, Object> send(Message message) {
         // 만약에 위의 @Constraints에 위배되는 값이 있다면 이 Set에 들어가게 된다
         Set<ConstraintViolation<Message>> violationSet = validator.validate(message);
    
         if (violationSet.isEmpty() == false) {
             // 만약에 Message.sender가 null이라면 이 Exception의 메세지는 
             // [class: Message, property: sender, message: may not be null]
             throw new IllegalArgumentException(
                 violationSet.stream()
                     .map(violation -> String.format("[class: %s, property: %s, message: %s]",
                             violation.getRootBeanClass().getSimpleName(),
                             violation.getPropertyPath().toString(),
                             violation.getMessage()))
                     .collect(Collectors.joining(", "))
             );
         }
    
         // 이하 생략
     }
    }
    

results matching ""

    No results matching ""