@ModelAttribute
-
[Spring] @RequestBody, @ModelAttribute2023.04.24
[Spring] @RequestBody, @ModelAttribute
@Valid annotation의 예외 처리하기
@PostMapping("/sign-up")
public String signUp(@Valid UserDTO userDto, BindingResult bindingResult) {
if(bindingResult.hasErrors()){
return "user/form";
}
userService.addUser(userDto);
return "redirect:/user/list";
}
기존에는 위와같은 방식으로 request를 UserDTO에 mapping할때 @Valid 과정에서 오류가 나면 bindingResult로 오류를 확인한후 user/form으로 재이동했다. 근데 이왕 @ControllerAdvice를 만들었으니 @Valid과정에서 발생하는 오류또한 @ControllerAdvice에서 처리를 해주고 싶었다.
MethodArgumentNotValidException, BindException
@Valid로 인해 발생하는 오류를 잡는 방법 2가지
@RequestBody로 받은 파라미터에서 오류가 발생하면 MethodArgumentNotValidException이 발생한다.
@ModelAttribute로 받은 파라미터에서 오류가 발생하면 BindException이 발생한다고 한다.
@RequestBody,@ModelAttribute로 request를 받을때 차이점
@RequestBody: 클라이언트가 보낸 HTTP 요청(JSON,XML..)을 Java 오브젝트로 변환한다. 이때 변환은 Spring에서 제공하는 HttpMessageConverter를 통해 타입에 맞는 객체로 변환이 된다. 이때 ObjectMapper를 통해 JSON값을 Java객체로 역직렬화하는데 따라서 dto에 setter(하지만 결국 바인딩을 위해선 setter 혹은 getter중 하나가 있어야한다. 단지 setter가 아닌 getter만 있더라도 데이터 바인딩이 가능하다는 것 이다.)가 없더라도 reflextion을 통해 값을 설정할수 있다.
- 역직렬화란 생성자를 거치지않고 리플렉션을 통해 객체를 구성하는 매커니즘
❗️직렬화가 가능한 클래스는 기본 생성자가 필수다. 따라서 @Requestbody에 사용하려는 Dto가 기본 생성자를 정의하지 않으면 데이터 바인딩에 실패한다.
즉 @RequestBody
를 사용할땐 기본생성자 + getter 또는 setter 가 필요하다.
@ModelAttribute: HTTP 파라미터들을 특정 Java Object에 바인딩 한다.
쿼리 또는 본문에 삽입되는 Form형태의 데이터를 처리할때 사용한다. @ModelAttribute의 특징으로는 객체에 접근을해 데이터를 바인딩 할 수 있는 생성자 혹은 setter가 필요하다.
ControllerAdvice 에서 서로다른 bindException 처리
따라서 나는 form의 데이터를 받는 형태니까 @ModelAttribute를 사용한다. 근데 이때 post와 sign-up 둘다 bindException이 발생할수 있는데 이걸 어떻게 처리하지?
@ExceptionHandler(BindException.class)
public ModelAndView handleBindException(BindException e, HttpServletRequest request){
String requestUri = request.getRequestURI();
if (requestUri.contains("/sign-up")) {
return createErrorResponseModelAndView("user/form", e,false);
}
return createErrorResponseModelAndView("article/form", e,false);
}
위와같이 HttpServletRequest를 통해 uri에 따라 viewName을 구분지었다.
따로 @RequestBody,@ModelAttribute를 명시하지 않을때 바인딩 되는 방식
HTTP 요청의 Content-Type이 application/x-www-form-urlencoded인 경우에는 @ModelAttribute
어노테이션과 동일한 방식으로 매개변수를 바인딩한다. 이 경우에는 HttpServletRequest.getParameter()
메서드를 사용하여 HTTP 요청 매개변수를 가져와서 자바 객체에 바인딩한다.
만약 HTTP 요청의 Content-Type이 application/json인 경우에는 @RequestBody
어노테이션과 동일한 방식으로 매개변수를 바인딩한다. 이 경우에는 HTTP 요청 본문에 포함된 JSON 문자열을 Jackson 등의 JSON 라이브러리를 사용하여 자바 객체로 역직렬화하고, 이 객체를 매개변수로 바인딩한다.
따라서, @ModelAttribute
어노테이션과 @RequestBody
어노테이션을 명시하지 않아도 Spring MVC는 HTTP 요청 매개변수를 자동으로 바인딩한다.
Reference
'Spring' 카테고리의 다른 글
@JdbcTest (0) | 2023.07.05 |
---|---|
@ActiveProfiles (0) | 2023.07.05 |
[SpringMVC] DTO 사용이유 (0) | 2023.04.09 |
[SpringMVC] addViewController사용할때 주의할점 (0) | 2023.04.09 |
[SPRING] Bean Scope (0) | 2023.03.05 |