ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Validation 추상화
    백기선(인프런 강의)/스프링 프레임워크 핵심 기술 2020. 3. 23. 22:37
    반응형

    org.springframework.validation.Validator

     

    스프링에서는 Validator 인터페이스를 지원하여 어플리케이션에서 사용하는 객체를 검증할 수 있는 기능을 제공한다. 이 Validator 인터페이스는 어떤 특정 계층에 사용하는 기능이 아닌 모든 계층에서 사용할 수 있다.

     

    Validator는 Java EE Spec인 Bean Validation의 어노테이션을 이용하여 객체가 제대로 요구사항에 맞추어 생성 됬는지 검증할 수 있다.



    특징

    • 어떤한 계층과도 관계가 없다. => 모든 계층(웹, 서비스, 데이터)에서 사용해도 좋다. 
    • 구현체 중 하나로, JSR-303(Bean Validation 1.0)과 JSR-349(Bean Validation 1.1)을 지원한다. (LocalValidatorFactoryBean
    • DataBinder에 들어가 바인딩 할 때 같이 사용되기도 한다. 

     

    코드 설명

     

    public class Event {
    	Integer id;
    	String title;
    
    	public Integer getId() {
    		return id;
    	}
    
    	public void setId(Integer id) {
    		this.id = id;
    	}
    
    	public String getTitle() {
    		return title;
    	}
    
    	public void setTitle(String title) {
    		this.title = title;
    	}
    
    }
    public class EventValidator implements Validator{
    
    	@Override
    	public boolean supports(Class<?> clazz) {
    		return Event.class.equals(clazz);
    	}
    
    	@Override
    	public void validate(Object target, Errors errors) {
    		// errors, field, 
    		// erroCode - key 값
    		// defaultMessage - 에러코드가 발생하지 않을때
    		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "title", "notempty", "Empty title is now allowed.");
    		Event event = (Event)target;
    		if(event.getTitle() == null) {
    			errors.reject("empty"); // 종합적으로 봤을 때 공통으로 사용할 때 사용
    			errors.rejectValue("title", "empty"); // 특정한 필드에 관련된 에러일 때 사용
    		}
    	}
    	
    }
    @Component
    public class AppRunner implements ApplicationRunner {
    
        @Override
        public void run(ApplicationArguments args) throws Exception {
            Event event = new Event();
            EventValidator eventValidator = new EventValidator();
            Errors errors = new BeanPropertyBindingResult(event, "event");
    
            eventValidator.validate(event, errors);
            System.out.println(errors.hasErrors());
    
            errors.getAllErrors().forEach(e->{
                System.out.println("==== error code ====");
                Arrays.stream(e.getCodes()).forEach(System.out::println);
                System.out.println(e.getDefaultMessage());
            });
        }
    }
    true
    ==== error code ====
    notempty.event.title
    notempty.title
    notempty.java.lang.String
    notempty
    Empty title is now allowed.

    boolean supports(Class clazz)

    • 어떤 타입의 객체를 검증할 때 사용할 것인지 결정함
    • 넘어온 인자의 객체의 클래스가 Event인지 검사

    void validate(Object obj, Errors e)

    • 실제 검증 로직을 이안에 구현
      • 구현할 때 ValidationUtils 사용하여 편리함
    • ValidationUtilsrejectIfEmptyOrWhitespace 메소드를 사용하여 객체의 title 필드가 비어있거나 공백일 때  error에 정보를 담았다.
    • "notempty" 는 에러코드
    • "Empty title is now allowed." 는 디폴드 메세지

    BeanPropertyBindingResult

    • 객체에 대한 에러정보를 담는 객체이며 Erros의 구현체
    • event객체에 에러가 있을 경우 이 객체에 정보가 담긴다,.
    • error를 통해 에러 정보를 구할 수 있다.
    • 실제로는 사용하지 않고 테스트용도로 사용

     

    Bean validation을 이용한 검증 로직

    public class Event {
        Integer id;
    
        @NotEmpty
        String title;
    
        @Min(0)
        Integer limit;
    
        @Email
        String email;
        
        public Integer getLimit() {
            return limit;
        }
    
        public void setLimit(Integer limit) {
            this.limit = limit;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    }
    @Component
    public class AppRunner implements ApplicationRunner {
    
        @Autowired
        Validator validator;
    
        @Override
        public void run(ApplicationArguments args) throws Exception {
            System.out.println(validator.getClass());
    
            Event event = new Event();
            event.setLimit(-1);
            event.setEmail("aaa2");
            Errors errors = new BeanPropertyBindingResult(event, "event");
    
            validator.validate(event, errors);
            System.out.println(errors.hasErrors());
    
            errors.getAllErrors().forEach(e->{
                System.out.println("==== error code ====");
                Arrays.stream(e.getCodes()).forEach(System.out::println);
                System.out.println(e.getDefaultMessage());
            });
        }
    }
    class org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
    true
    ==== error code ====
    Min.event.limit
    Min.limit
    Min.java.lang.Integer
    Min
    must be greater than or equal to 0
    ==== error code ====
    NotEmpty.event.title
    NotEmpty.title
    NotEmpty.java.lang.String
    NotEmpty
    반드시 값이 존재하고 길이 혹은 크기가 0보다 커야 합니다.
    ==== error code ====
    Email.event.email
    Email.email
    Email.java.lang.String
    Email
    이메일 주소가 유효하지 않습니다.

     

     

    스프링 부트 2.0.5 이상 버전을 사용할 때 

    • LocalValidatorFactoryBean 빈으로 자동 등록
    • JSR-380(Bean Validation 2.0.1) 구현체로 hibernate-validator 사용.
    • https://beanvalidation.org/

     

     

     

    반응형
Designed by Tistory.