찌니의 프로그래밍 삼매경

[Spring Boot] @Valid 어노테이션으로 파라미터 검증 본문

Spring

[Spring Boot] @Valid 어노테이션으로 파라미터 검증

zzI니☆ 2021. 6. 19. 19:22
728x90

 

 


 

@Valid 어노테이션으로 파라미터 검증하기

따로 dependency해 줄 필요가 없었지만 지금은 dependency 해줘야 작동하는듯하다..

 

valid 라이브러리 받는 곳

https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation

 

나는 2.4.4 버전을 사용한다.

<!-- Maven -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>2.4.4</version>
</dependency>


<!-- Gradle -->
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation', version: '2.4.4'

 

 

 

 


javax.validation이 제공하는 어노테이션

 

Anotation 제약조건
@NotNull Null 불가
@Null Null만 입력 가능
@NotEmpty Null, 빈 문자열 불가
@NotBlank Null, 빈 문자열, 스페이스만 있는 문자열 불가
@Size(min=,max=) 문자열, 배열등의 크기가 만족하는가?
@Pattern(regex=) 정규식을 만족하는가?
@Max(숫자) 지정 값 이하인가?
@Min(숫자) 지정 값 이상인가
@Future 현재 보다 미래인가?
@Past 현재 보다 과거인가?
@Positive 양수만 가능
@PositiveOrZero 양수와 0만 가능
@Negative 음수만 가능
@NegativeOrZero 음수와 0만 가능
@Email 이메일 형식만 가능
@Digits(integer=, fraction = ) 대상 수가 지정된 정수와 소수 자리 수 보다 작은가?
@DecimalMax(value=)  지정된 값(실수) 이하인가?
@DecimalMin(value=) 지정된 값(실수) 이상인가?
@AssertFalse false 인가?
@AssertTrue true 인가?

 


 

현재 진행중인 프로젝트의 회원가입부분에 적용해보았다.

postman을 이용해 확인해보자.

 

 

회원가입 요청을 받으면 파라미터를 @Valid로 받아 Custom으로만든 Exception 메세지를 보여주도록 처리했다.

 

Controller

package com.leo.photogram.web;

import com.leo.photogram.domain.user.User;
import com.leo.photogram.handler.ex.CustomValidationException;
import com.leo.photogram.service.AuthService;
import com.leo.photogram.web.dto.auth.SignupDto;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

@RequiredArgsConstructor
@Controller
public class AuthController {

    private static final Logger log = LoggerFactory.getLogger(AuthController.class);

    private final AuthService authService;

    @GetMapping("/auth/signin")
    public String signinForm(){
        return "auth/signin";
    }

    @GetMapping("/auth/signup")
    public String signupForm(){
        return "auth/signup";
    }

    @PostMapping("/auth/signup")
    public String signup(@Valid SignupDto signupDto, BindingResult bindingResult){

        if(bindingResult.hasErrors()){
            Map<String, Object> errorMap = new HashMap<>();

            for(FieldError error : bindingResult.getFieldErrors()){
                errorMap.put(error.getField(), error.getDefaultMessage());
            }
            throw new CustomValidationException("유효성 검사 실패", errorMap);
        }else{
            log.info(signupDto.toString());
            User user = signupDto.toEntity();
            User res = authService.signUp(user);
            log.info("회원가입결과 > " + res.toString());
            return "auth/signin";
        }
    }
}

 


DTO

1. SignupDto

package com.leo.photogram.web.dto.auth;

import com.leo.photogram.domain.user.User;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

@Data
public class SignupDto {

    @Size(min = 2, max = 20)
    @NotBlank
    private String username;

    @NotBlank
    private String password;
    @NotBlank
    private String email;
    @NotBlank
    private String name;

    public User toEntity(){
        return User.builder()
            .username(username)
            .password(password)
            .email(email)
            .name(name)
            .build();
    }
}

2. CommRespDto<T>

package com.leo.photogram.web.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Map;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class CommRespDto<T> {

    private int resultCode;   // 1 성공 , 9999 실패
    private String message;
    private Map<String,Object> errorMap;
}

ControllerExceptionHandler

package com.leo.photogram.handler;

import com.leo.photogram.handler.ex.CustomValidationException;
import com.leo.photogram.web.dto.CommRespDto;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@ControllerAdvice
public class ControllerExceptionHandler {

    @ExceptionHandler(CustomValidationException.class)
    public CommRespDto<?> validationException(CustomValidationException e){
        return new CommRespDto<Map<String,Object>>(9999 ,e.getMessage(), e.getErrorMap());
    }
}

CustomValidationException

package com.leo.photogram.handler.ex;

import java.util.Map;

public class CustomValidationException extends RuntimeException{

    private Map<String, Object> errorMap;

    public CustomValidationException(String message, Map<String,Object> errorMap){
        super(message);
        this.errorMap = errorMap;
    }

    public Map<String, Object> getErrorMap() {
        return errorMap;
    }
}

 

 


 

@Size(min = 2, max = 20)와 @NotBlank를 통과하지 못한 username과 password에 대한 message를 확인할 수 있다.

@NotBlank는 null, 빈 문자열, 스페이스공백 입력 불가

 

회원가입 요청 등 프로그램을 구성할 때 유용하게 사용할 수 있다.

끝.

728x90
Comments