티스토리 뷰

728x90

@Valid는 객체 단계에서 프러퍼티의 유효성을 검사 할 수 있어서 로직이 지저분해지는걸 막을 수 있다.

1️⃣ maven

<dependency>
   <groupId>javax.validation</groupId>
   <artifactId>validation-api</artifactId>
   <version>2.0.1.Final</version>
</dependency>
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>5.2.4.Final</version>
</dependency>

2️⃣ bean 설정

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:mvc="http://www.springframework.org/schema/cache"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
   
    <!-- Integration Apache Commons Validator by Spring Modules -->
    <bean id="beanValidator" class="org.springmodules.validation.commons.DefaultBeanValidator">
       <property name="validatorFactory" ref="validatorFactory"/>
    </bean>

    <bean id="validatorFactory" class="org.springmodules.validation.commons.DefaultValidatorFactory">
       <property name="validationConfigLocations">
           <list>
               <!-- 경량환경 템플릿 밸리데이터 설정 -->
               <value>classpath:/egovframework/validator/validator-rules-let.xml</value>
               <value>classpath:/egovframework/validator/let/**/*.xml</value>
           </list>
       </property>
    </bean>
<!-- Invokes Spring MVC @Controller methods -->
   <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
      <property name="webBindingInitializer">
         <!-- Configures Spring MVC DataBinder instances -->
         <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="validator" ref="validator" />
         </bean>
      </property>
   </bean>
<!-- Creates the JSR-303 Validator -->
   <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
</beans>

3️⃣

1. vo

- ⭐import를 주의하자! (import org.hibernate.validator.constraints.NotBlank;)

- @NotBlank는 String에 붙이는 것으로 null과 공백을 제거한 문자열의 길이가 0이면 안된다.

- message를 붙여주면 메세지를 커스터마이징 할 수 있다. 붙이지 않는 경우 기본 메세지

import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;

@Data
public class ShareImageVO {
    @NotBlank(message = "roomUuid는 필수값 입니다.")
    private String roomUuid;
    @NotBlank(message = "이미지 url은 필수값 입니다.")
    private String imageUrl;
    private String imageName;
}

2. controller

- 객체에 @Valid 어노테이션을 붙여주면, 컨트롤러 로직을 타기 전에 유효성 검사를 실시한다.

@RestController
@RequestMapping("api/v1/")
public class ApiController {
    @RequestMapping(value ="share/image", method = RequestMethod.POST)
    public ApiResponse shareImage(@RequestBody @Valid ShareImageVO shareImage) {
        ApiResponse apiResponse = new ApiResponse();
        apiResponse.setCode(HttpStatus.OK.value());
        apiResponse.setMessage(HttpStatus.OK.name());
        websocketController.shareImage(shareImage);
        return apiResponse;
    }
}

📌Error

-@Valid를 적용한 경우 유효성 검사에 실패하면 발생 하는 에러는 MethodArgumentNotValidException 이다.

그런데 나는...계속 UnexpectedTypeException가 났다..심지어 roomUuid와 imageUrl에 값을 넣었는데도 UnexpectedTypeException 에러가 났다...why..

HV000030: No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.String'. 

검색을 해보니 보통 String 타입이 아닌 다른 타입에 String 타입에만 사용해야하는 @notEmpty, @notBlank를 사용해서 나는 것 같았다. 그렇지만 나는 String 타입에 사용했는데..?

 

문제는 import를 잘못해서 생긴 발생했다.

org.hibernate.validator.constraints.NotBlank;를 임포트 해야하는데 아래와 같이 javax.validation.constraints.NotBlank를 임포트 했다.import를 변경 해주니 제대로 정상 작동 했다.

import의 중요성...블로거들이 대부분 import를 작성 안하는데, 작성해주면 좋겠다.😂

@ControllerAdvice
@ResponseBody
public class ApiExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ApiResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        String errorMessage = e.getBindingResult()
                .getAllErrors()
                .get(0)
                .getDefaultMessage(); //vo에서 설정한 메세지를 가져온다.

        ApiResponse apiResponse = new ApiResponse();
        apiResponse.setCode(HttpStatus.BAD_REQUEST.value());
        apiResponse.setMessage(errorMessage);

        return ResponseEntity.badRequest().body(apiResponse);
    }
}

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함