minlog
article thumbnail

 

메서드를 사용하거나, 정규식과 비교해주는 어노테이션을  외에도 별도의 정규식을 만들어서 사용 할 수 있다. 

 

별도의 정규식을 추가하는 필요성?

보통 날짜 부분에서 많이 사용된다. String 형으로 받아오게되는데, 명확히 확인 될 수 있는 정규식이 없다.

예시로 년도와 달 6글자를 받는 필드가 있다고 할때, 조건을 더 추가해주지 않으면 글자 수가 맞다면 날짜가 일치 하지 않아도 실행에 성공하게 된다. 각 사이트의 비즈니스 로직에 맞는 정규식이 필요하다.

@Size(min=6,max = 6,message = "날짜를 정확하게 입력해주세요 ex ) yyyyMM")
private String reqYearMonth;

 

 

 

 

1. @AssertTrue/False  어노테이션 사용

필드를 가져와서 정해진 패턴과 비교해주는 별도의 메서드를 만들어줄 수 있다.

@AssertTrue 어노테이션, is 가 포함된 메서드 명을 반드시 넣어주어야한다.

 

  • 파싱이 잘되면 true를 반환하여 값이 노출되고, 파싱이 실패한다면 false를 반환하여 에러 메시지가 노출된다.
  • 내부에 바로 받아주는 필드의 명을를 적게 되어 재활용이 불가능하다.

 

📑 User.java

@AssertTrue
public boolean isReqYearMonthValidation(){
    this.reqYearMonth=getReqYearMonth()+"01";
    try {
    	//실제 날짜 패턴과 비교해주는 부분
        LocalDate localDate = LocalDate.parse(this.reqYearMonth, DateTimeFormatter.ofPattern("yyyyMM"));

    }catch (Exception e){
        return false;
    }

    return true;
}

 

 

 

 

 

2. 재사용이 가능한 커스텀 어노테이션을 생성.

정규식을 실행해주는 비즈니스 로직이 들어간 어노테이션을 직접 만들어 사용이 가능하다.

 

1) 어노테이션 인터페이스

📑 YearMonth.java 

package com.example.validation.anotation;

import com.example.validation.Validator.YearMontValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Constraint(validatedBy = {YearMontValidator.class})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)

public @interface YearMonth {
    String message() default "yyyyMM의 형식에 맞지 않습니다.";

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

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

    String pattern() default "yyyyMM"; // 어떤 형식으로 받아줄지 지정하여 주는 부분. - 기본패턴
}

 

 

2) 실제 정규식 로직이 들어간 클래스

ConstraintValidator 객체를 통해 어노테이션 인터페이스받아오는 문자를 넣어서 실행 결과를 반환해주는 클래스

📑 YearMonthValidator.java

package com.example.validation.Validator;

import com.example.validation.anotation.YearMonth;

import javax.swing.*;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class YearMontValidator implements ConstraintValidator<YearMonth,String> {
    String pattern;

    @Override
    public void initialize(YearMonth constraintAnnotation) {
        this.pattern = constraintAnnotation.pattern();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        //value yyyyMM  value+"01"
        try {
            LocalDate localDate = LocalDate.parse(value+"01", DateTimeFormatter.ofPattern("yyyyMM"));

        }catch (Exception e){
            return false;
        }

        return true;
    }
}

 

3) 사용될 필드 부분에서 어노테이션 선언

 

📑 User.java

@YearMonth
private String reqYearMonth;

 

 

4) 컨트롤러에서 객체 받아오는 부분

📑 ApiController.java

package com.example.validation.controller;

import com.example.validation.dto.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequestMapping("/api")
public class ApiController {
    @PostMapping("/user")
    public ResponseEntity user(@Valid @RequestBody User user, BindingResult bindingResult){

        if(bindingResult.hasErrors()){
            StringBuilder sb = new StringBuilder();
            bindingResult.getAllErrors().forEach(objectError -> {
                //오브젝트의 에러를 받아서.
                    //어떤 필드의 에러인지 오브젝트 에러를 형변환하여 넣어준다.
                    // 메시지를 통해 에러의 내용도 알수 있다.
                FieldError field = (FieldError) objectError;
                String message = field.getDefaultMessage();

                System.out.println("필드 :" + field.getField());
                System.out.println("에러 내용 :" + message);
                sb.append("field : "+field.getField());
                sb.append("message : "+message);
            });

            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(sb.toString());
        }

        return ResponseEntity.ok(user);
    }
}

 

 

 

※ 만약 객체 클래스 안에 다른 객체가 있고 그안에서도 validation을 검사해줘야할때, 객체 필드에도 @Valid  어노테이션을 선언해주어야한다.

 

📑 user.java

@Valid
private List<Car> cars;

 

📑 Car.java

@NotNull
private carName;

 

profile

minlog

@jimin-log

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!