API를 구현할 때, post 메소드로 body에 데이터를 받는다.
이 때 값들이 유효한 값인지를 검증하여 유효하지 않으면 bad request를 보낼 수가 있다.
간단하고 유용하게 사용할 수 있는 것이 javax.validation.constraints에 있는 애노테이션들이다.
spring-boot-starter-web
의존성을 추가할 경우에는 딸려 들어온다.
1,2,3의 값 만을 받아야 하는 priority
필드가 있다고 하면
이 때 아래처럼 사용하면 됨.
UpdateTodoRequestDto.class
1
2
3
4
5
6
7
8
9
10
@NoArgsConstructor
@Getter
public class UpdateTodoRequestDto {
@NotNull(message = "우선순위를 입력해주세요.")
@Min(value = 1, message = "우선순위는 1~3 사이의 값이어야 합니다.")
@Max(value = 3, message = "우선순위는 1~3 사이의 값이어야 합니다.")
private Long priority;
//...
}
TodoController.class
1
2
3
4
5
6
7
8
9
10
11
12
13
@Slf4j
@CrossOrigin
@RestController
@RequestMapping(value = "/api/todos", produces = "application/hal+json")
public class TodoController {
@PutMapping("/{id}")
public int updateTodo(@PathVariable Long id, @Valid @RequestBody UpdateTodoRequestDto dto) {
log.info("PUT :: /api/todos/" + id + " dto :: " + dto);
return todoService.updateTodoWithTitleAndContentAndClosingDateAndPriority(id, dto);
}
...
}
Controller에서 dto 앞에 @Valid
를 추가 해주어야 적용 됨.
request
response
가공하기
위의 response처럼 모든 데이터를 응답하지 않고 특정 필드만 응답할 수 있다.
예를들어, message와 field만을 전송하고 싶다면 다음과 같이 예외처리를 해주면 된다.
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
31
32
33
34
35
@ControllerAdvice // 빈등록
public class GlobalExceptionHandler {
@ExceptionHandler
public ResponseEntity<String> notValidException(MethodArgumentNotValidException e) {
ErrorDetails errorDetails = new ErrorDetails(
e.getBindingResult().getFieldError().getField(),
e.getBindingResult().getFieldError().getDefaultMessage());
return new ResponseEntity(errorDetails, HttpStatus.BAD_REQUEST);
}
@Getter
private class ErrorDetails {
private String field;
private String message;
public ErrorDetails(String field, String message) {
this.field = field;
this.message = message;
}
@Override
public String toString() {
return "ErrorDetails{" +
"errorField='" + field + '\'' +
", message='" + message + '\'' +
'}';
}
}
}
request
response
간결해졌다.
테스트
TodoControllerTest.class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RunWith(SpringRunner.class)
@WebMvcTest(TodoController.class)
public class TodoControllerTest {
@Test
public void 우선순위가_4인_Todo_저장요청시_BadRequest() throws Exception {
//given
SaveTodoRequestDto dto = SaveTodoRequestDto.builder().title("제목").content("내용").priority(4L).build();
//when
mockMvc.perform(post("/api/todos")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(jsonStringFromObject(dto)))
//then
.andDo(print())
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.message",is("우선순위는 1~3 사이의 값이어야 합니다.")));
}
}
Comments powered by Disqus.