일반적인 어플리케이션에서 사용되던 validation 방식은 몇가지 문제가 존재
앞서 나온 문제를 해결하기 위해 Java에서 2009년부터 Bean Validation이라는 데이터 유효성 검사 프레임워크를 제공
Bean Validation은 어노테이션을 통해 다양한 데이터를 검증할 수 있게 기능을 제공
Hibernate Validator는 Bean Validation 명세에 대한 구현체
Spring Boot의 유효성 검사 표준은 Hibernate Validator를 채택
이전 버전의 SpringBoot에서는 starter-web에 validation이 포함되어 있었지만, 2.3버전부터 starter-validation을 추가해야 함
---실습---
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
ProductDto.java
package com.example.testproject.data.dto;
import com.example.testproject.data.entity.ProductEntity;
import lombok.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ProductDto {
//@ize(min=8, max=8)
@NotNull
private String productId;
@NotNull
private String productName;
@NotNull
@Min(value=500)
@Max(value=300000)
private int productPrice;
@NotNull
@Min(value=0)
@Max(value=9999)
private int productStock;
public ProductEntity toEntity(){
return ProductEntity.builder()
.productId(productId)
.productName(productName)
.productPrice(productPrice)
.productStock(productStock)
.build();
}
}
// http://localhost:8080/api/v1/product-api/product
@PostMapping(value = "/product")
public ResponseEntity<ProductDto> createProduct(@RequestBody ProductDto productDto) {
String productId = productDto.getProductId();
String productName = productDto.getProductName();
int productPrice = productDto.getProductPrice();
int productStock = productDto.getProductStock();
ProductDto response=productService.saveProduct(productId,productName,productPrice,productStock);
LOGGER.info(
"[createProduct] Response >> productId : {} , productName : {} , productPrice : {}, productStock : {}",
response.getProductId(), response.getProductName(), response.getProductPrice(), response.getProductStock()
);
return ResponseEntity.status(HttpStatus.OK).body(response);
}
결과
[2022-10-19 01:04:50.359] [INFO ] [http-nio-8081-exec-8] c.e.t.c.ProductController [createProduct] Response >> productId : string , productName : string , productPrice : -800, productStock : 0
swagger-ui로 확인했을때 응답이 200대로 오류가 전혀 발생하지 않았음을 알 수 있음.
=> 앞서 설정한 제약조건들이 적용되지 않았음
// http://localhost:8080/api/v1/product-api/product
@PostMapping(value = "/product")
public ResponseEntity<ProductDto> createProduct(@Valid @RequestBody ProductDto productDto) { //****이부분에 어노테이션 Valid 붙여줬음****
String productId = productDto.getProductId();
String productName = productDto.getProductName();
int productPrice = productDto.getProductPrice();
int productStock = productDto.getProductStock();
ProductDto response=productService.saveProduct(productId,productName,productPrice,productStock);
LOGGER.info(
"[createProduct] Response >> productId : {} , productName : {} , productPrice : {}, productStock : {}",
response.getProductId(), response.getProductName(), response.getProductPrice(), response.getProductStock()
);
return ResponseEntity.status(HttpStatus.OK).body(response);
}
결과 : 이제는 400대 에러 발생함
[2022-10-19 01:11:36.402] [WARN ] [http-nio-8081-exec-8] o.s.w.s.m.s.DefaultHandlerExceptionResolver Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity<com.example.testproject.data.dto.ProductDto> com.example.testproject.controller.ProductController.createProduct(com.example.testproject.data.dto.ProductDto): [Field error in object 'productDto' on field 'productPrice': rejected value [-800]; codes [Min.productDto.productPrice,Min.productPrice,Min.int,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [productDto.productPrice,productPrice]; arguments []; default message [productPrice],500]; default message [500 이상이어야 합니다]] ]
//참고 코드 //Validation code Example if (productDto.getProductId().equals("") | productDto.getProductId().isEmpty()){ LOGGER.error("[createProduct] failed Response :: productId is Empty"); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(productDto); }