본문 바로가기

Spring

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

728x90
반응형

Gradle 추가 

 implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation'

 

ProductInfo.java

package com.heypli.productsvc.domain.request;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.validation.constraints.NotNull;

@Getter
@Setter
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
public class ProductInfoRequest {

    @NotNull(message = "{valid.notnull}")
    private Long        prodId;
    private String      prodName;
    private String      prodDesc;
}

javax.validation 

Annotation 설명
@NotNull Null 불가
@Null Null만 입력 가능
@NotEmpty Null, 빈 문자열 불가능
@NotBlank Null, 빈문자열, 스페이스만 있는 문자열 불가능
@Size(min=,max=) 문자열길이 체크
@Pattern(regex=) 정규식체크
@Max 지정값 이하인지 체크
@Min 지정값 이상인지 체크 

등등 많지만 이 정도만 일단..

ProductController.java

 @PostMapping("/getProdList")
    public ResponseEntity<CommonListResponse<ProductInfoResponse>> getProdList(@Valid @RequestBody ProductInfoRequest param) throws Exception {

        CommonListResponse<ProductInfoResponse> result = productService.getProdList(param);

        return new ResponseEntity<>(result, HttpStatus.OK);
    }

@RequestBody 로 들어오는 데이터를 검증할 수 있다.

@Valid를 붙여 주면 된다.

@RequestBody로 들어오는 값을 검증하기 때문에 GET 메소드와 사용할 수 없다.

 

 


@Valid 어노테이션 message에 messages.properties 파일의 값 사용

WebConfig.java

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Locale;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**");
    }

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource source = new ReloadableResourceBundleMessageSource();
        source.setBasename("classpath:/messages/messages");
        source.setDefaultEncoding("UTF-8");
        source.setUseCodeAsDefaultMessage(true);
        source.setDefaultLocale(Locale.KOREA);
        return source;
    }

    @Bean
    public LocalValidatorFactoryBean getValidator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }
}

resources/messages/messages.properties

에 사용할 메세지를 작성한다.

원래 SpringBoot에 MessageSource가 포함되어 있기 때문에 따로 빈설정을 하지 않아도 되지만 getValidator를 쓰기 위해 빈설정을 했다. setBeanName에 messages/messages를 쓰면 messages폴더 밑에 있는 messages*.properties 파일을 읽는다.

getValidator()는 DTO에서 messageSource를 가지고 올 수 있게 해주는 역할을 해준다. 

 

messages.properties

valid.notnull=필수 항목이 누락되었습니다.

 

Valid에러 잡아서 리턴 

ErrorHandler.java

@ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<CommonResponse> handleException(HttpServletRequest request, HttpServletResponse response,
                                                          MethodArgumentNotValidException exception) {
        List<ObjectError> allErrors = exception.getBindingResult().getAllErrors();
        Map<String, String> errors = new HashMap<>();

        for(ObjectError err: allErrors) {
            if(FieldError.class.isAssignableFrom(err.getClass())) {
                errors.put(((FieldError) err).getField(), err.getDefaultMessage());
            } else {
                errors.put(err.getObjectName(), err.getDefaultMessage());
            }
        }

        String errMsg = "";

        try {
            errMsg = objectMapper.writeValueAsString(errors);
        } catch (JsonProcessingException e) {
            log.error(e.getMessage());
        }


        return ResponseEntity.status(response.getStatus()).body(new CommonResponse(RespCode.ERROR, errMsg));

    }

 

리턴값

{
    "returnCd": "ERROR",
    "message": "{\"prodId\":\"필수 항목이 누락되었습니다.\"}"
}
728x90
반응형