Validation

- dependencies에 추가

implementation 'org.springframework.boot:spring-boot-starter-validation'java

 

-user

public class User {

    @NotBlank
    private String name;

    @Max(value=120)
    private int age;

    @Email
    private String email;

    @Pattern(regexp="^\\d{2,3}-\\d{3,4}-\\d{4}$",message = "휴대폰 번호의 양식이 올바르지 않습니다.(01X-XXX(X)-XXXX)")
    private String phoneNumber;                 //fieldError.getDefaultMessage()할 때 이 메시지가 default메시지가 됨

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", email='" + email + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                '}';
    }java

 

-컨트롤러

@PostMapping("/user") 

public ResponseEntity user(@Valid @RequestBody User user, BindingResult bindingResult){

    //클래스에 사용한 validation을 사용하려면 해당 클래스를 사용하는 메서드 파라미터 속에 @Valid 있어야함
    //bindingResult=>결과..

 
StringBuilder sb=new StringBuilder();
    if(bindingResult.hasErrors()){
        bindingResult.getAllErrors().forEach(error->{
            FieldError fieldError=(FieldError)error;        //객체 속성 에러
            String message=fieldError.getDefaultMessage();

            sb.append("field : " +((FieldError) error).getField()); //객체 속성 이름 얻기
            sb.append(message);

            System.out.println(sb.toString());
        });
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(sb.toString());   //응답과 body를 한꺼번에 내려줌
    }

    return ResponseEntity.ok(user);
}java

 

 

<custom validation 만들기>

방법1) dto클래스 안에 @AssertThat 붙여진 메서드 만들기

방법2) 검증 어노테이션 만들기     => 재사용 가능!

 

-방법1)

- User-

@Size(min=6,max=6)
private String reqYearMonth;    //현업에서는 날짜를 string으로 받아서 처리(그리고 localdate 등으로 파싱)

@AssertTrue//(message='')로 메세지도 줄 수 있음 //리퀘스트를 내려줄 때 자동으로 이 메서드 실행. true를 반환하면 ok, false를 반환하면 400오류 발생
public boolean isReqYearMonthValidation(){      //@AssertTrue의 메서드의 이름은 is로 시작해야 하고, 반환값은 bool이어야 한다.
    try{
        LocalDate localDate=LocalDate.parse(reqYearMonth+"01", DateTimeFormatter.ofPattern("yyyyMMdd"));     //yyyyMMdd형식으로 파싱
        //LocalDate, LocalTime, LocalDateTime => 날짜, 시간, 날짜시간 객체
        //파싱(Parsing) : string -> LocalDate, LocalDateTime 으로 변환
        // ㄴ DateTimeFormatter를 설정해 주지 않으면 기본적으로 ISO_LOCAL_DATE 포멧터를 사용해서 파싱한다.(yyyy-MM-dd 형식)
    }catch (Exception e){
        return false;
    }
    return true;
}java

 => 이게 커스텀 로직 처리하는 방법1. 이렇게 해도 되지만, 이걸 검사하려는 객체가 여러개면 해당 객체마다 메서드를 작성해야

=> 검사하는 어노테이션을 만들어서 해당 어노테이션이 붙은 객체는 검사가 되게 하자! => 방법2!

 

 

방법2)

 

-내가 만든 어노테이션-

@Constraint(validatedBy = YearMonthValidator.class)     // 검증을 구현한 클래스
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface YearMonth {
    //밑의 메서드들은 어노테이션 다음에 ()안에 오는 변수들이다. ex. @YearMonth(message="~~")
    String message() default "yyyyMM 형식에 맞지 않습니다.";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

    //message, groups, payload이 세개는 빠져선 안된다.

    String pattern() default "yyyyMMdd";  //객체 변수위에 @Pattern 안해주면 이 디폴트패턴을 지켜야함
}java

 

-해당 어노테이션의 기능을 구현한 클래스-

private String pattern; //검증의 척도

@Override //초기화
public void initialize(YearMonth constraintAnnotation) {
    pattern = constraintAnnotation.pattern();
}

@Override //검증의 기준. true면 ok, false면 400오류
public boolean isValid(String value, ConstraintValidatorContext context) {  //value=이걸로 검증되는 변수의 값
    try{
        LocalDate localDate=LocalDate.parse(value+"01", DateTimeFormatter.ofPattern(pattern));
    }catch (Exception e){
        return false;
    }
    return true;
}java

 

-User-

@YearMonth
private String reqYearMonth;java

 

 

- 클래스안에 객체를 두는데 그 객체가 검증 어노테이션이 있고 이걸 적용하고 싶으면

그 객체 위에 @Valid를 붙여야 하는것에 명심!

-User

@Valid
private List<Car> cars;java

 

'BackEnd > 패캠' 카테고리의 다른 글

Filter (근데 이제 롬복을 곁들인)  (0) 2022.01.23
Exception 처리  (0) 2022.01.22
AOP 실무 사례 알아보기  (0) 2022.01.20
AOP  (0) 2022.01.19
Ioc, DI  (0) 2022.01.18