스프링 입문
[스프링 입문] 6.2 Spring Boot Custom Validation
코딩펭귄
2024. 1. 8. 23:51
Custom Validation
1. AssertTrue / False 와 같은 method지정을 통해 Custom Logic 적용 가능(재사용 불가)
2. CustomValidator를 적용하여 재사용이 가능한 Custom Logic 적용가능
@AssertTrue -> "is" 라는 키워드로 항상 메소드가 시작해야 됨
@AssertTrue(message = "yyyyMM의 형식에 맞지 않습니다.")
public booldean isReqYearMonthValidation(){
System.out.println("assert true call");
try{
LocalDate localDate = LocalDate.parse(getReqYearMonth() + "01", DateTimeFormatter.ofPattern("yyyyMMdd"));
}catch (Exception e){
return false;
}
return true;
}
YearMonth 라는 annotation 만들기(custom) 예제 (6.1 예제 참고)
import com.example.validation.validator.YearMonthValidator;
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 = {YearMonthValidator.class}) //YearMonthValidator의 클래스를 가지고 검사가 이루어짐
@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 "yyyyMMdd";
}
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.*;
@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 = objectError.getDefaultMessage();
System.out.println("field : "+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);
}
}
* 특정 클래스, 변수에 대해 검사를 하고싶다?(그것이 object 형태라면) : @Valid 꼭 붙여줘야됨
dto-User 파일에 추가하기
@Valid // 검사하고싶다면 꼭 Valid 어노테이션 붙여주기
private List<Car> cars;
import com.example.validation.annotation.YearMonth;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class YearMonthValidator implements ConstraintValidator<YearMonth, String> {
private String pattern;
@Override
public void initialize(YearMonth constraintAnnotation) {
this.pattern = constraintAnnotation.pattern(); //정상적으로 값 들어갔는지 확인
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// value값이 확인하고자 하는 yyyyMM
try{ //value+'01' 로 하는 이유 : 자동적으로 month에대해 검색이 되기 때문(local date이기 때문)
LocalDate localDate = LocalDate.parse(value+"01" , DateTimeFormatter.ofPattern(this.pattern));
}catch (Exception e){
return false;
}
return true;
}
}
import com.fasterxml.jackson.annotation.JsonProperty;
public class Car {
@NotBlank
private String name;
@NotBlank
@JsonProperty("car_number")
private String carNumber;
@NotBlank
@JsonProperty("TYPE") //대문자
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCarNumber() {
return carNumber;
}
public void setCarNumber(String carNumber) {
this.carNumber = carNumber;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", carNumber='" + carNumber + '\'' +
", type='" + type + '\'' +
'}';
}
}