-
Spring MVC(@ModelAttribute, @Valid, @Validated)웹개발/Spring 2020. 7. 28. 01:17
이 내용은 인프런의 스프링 웹 MVC강좌를 참고하여 만들었습니다.
1,@ModelAttribute
- 파라미터로 오는 사항들을 파라미터 타입을 임의 클래스 타입으로 받아오면서 파라미터 명과 필드명이 같으면 자동으로 매핑이 되어 저장이 됨
- 바인딩 오류 시에는 오류 발생, 그러나 BindingResult변수를 이용하여서 오류를 발생시키지 않고 타입이 다르면 null값을 대신 저장 후 오류 사항을 메시지 형태로 출력이 가능
-해당 선언 후 자동으로 진행이 되는 작업
1, MemberInfo클래스의 객체(받아오는 객체) info를 자동으로 생성
2, 해당 파라미터 명으로 자동으로 매핑이 됨
3, 자동으로 Model객체에 추가가 되고 뷰까지 전달이 됨
-()안에 오는 인자는 지정한 문자열의 이름으로 MenberInfo 객체가 Model객체로 추가될 때 해당 이름으로 사용(session이름이랑 겹치면 안됨)
- 생략이 가능함
Event class
public class Event { private Integer id; private String name; private Integer limit; public Integer getLimit() { return limit; } public void setLimit(Integer limit) { this.limit = limit; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
@Controller public class SampleController { @PostMapping("/events") @ResponseBody public Event getEvent(@Valid @ModelAttribute Event event, BindingResult bindingResult) { System.out.println(bindingResult.hasErrors()); if(bindingResult.hasErrors()){ System.out.println("==============================="); bindingResult.getAllErrors().forEach(c -> { System.out.println(c.toString()); }); return null; } return event; } }
테스트 코드
1, 정상적인 바인딩이 일어난 경우
@RunWith(SpringRunner.class) @WebMvcTest public class SampleControllerTest { @Autowired MockMvc mockMvc; @Test public void testEvent() throws Exception{ mockMvc.perform(post("/events") .param("id", "1") .param("name","test") .param("limit","10")) .andDo(print()) .andExpect(status().isOk()) .andExpect(jsonPath("name").value("test")) ; } }
2, 바인딩 오류인 경우
@RunWith(SpringRunner.class) @WebMvcTest public class SampleControllerTest { @Autowired MockMvc mockMvc; @Test public void testEvent() throws Exception{ mockMvc.perform(post("/events") .param("id", "1") .param("name","test") .param("limit","abc")) .andDo(print()) .andExpect(status().isOk()) ; } }
원래는 바인딩 오류이나 테스트는 통과가 되고 컨트롤러의 프린트문에 의하여 바인딩 오류 부분 확인 가능
2,@Valid, @Validated
- 변수에 조건을 주어 @ModelAttribute을 통하여 바인딩이 일어날 때 타입 이외의 조건에 의하여도 오류가 발생이 되도록 처리를 함
- validation을 하기 위하여는 다음과 같은 의존성을 추가해야 함
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.5.Final</version> </dependency>
Event class에 validate 조건을 줌
public class Event { private Integer id; @NotBlank private String name; @Min(value = 0) private Integer limit; public Integer getLimit() { return limit; } public void setLimit(Integer limit) { this.limit = limit; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
@Controller public class SampleController { @PostMapping("/events") @ResponseBody public Event getEvent(@Valid @ModelAttribute Event event, BindingResult bindingResult) { System.out.println(bindingResult.hasErrors()); if(bindingResult.hasErrors()){ System.out.println("==============================="); bindingResult.getAllErrors().forEach(c -> { System.out.println(c.toString()); }); return null; } return event; } }
위와 같이 유효성을 추가 할 수 있다.
- @Validated같은 경우에는 유효성마다 그룹화를 지어서 해당 그룹만 유효 조사를 할 수 있는 느낌이다.
Event class
public class Event { interface ValidateLimit{} interface ValidateName{} private Integer id; @NotBlank(groups = ValidateName.class) private String name; @Min(value = 0, groups = ValidateLimit.class) private Integer limit; public Integer getLimit() { return limit; } public void setLimit(Integer limit) { this.limit = limit; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
@Controller public class SampleController { @PostMapping("/events") @ResponseBody public Event getEvent(@Validated(Event.ValidateLimit.class) @ModelAttribute Event event, BindingResult bindingResult) { System.out.println(bindingResult.hasErrors()); if(bindingResult.hasErrors()){ System.out.println("==============================="); bindingResult.getAllErrors().forEach(c -> { System.out.println(c.toString()); }); return null; } return event; } }
name의 유효성 검사는 진행하지 않고 limit에 대한 검사만 진행을 한다.
'웹개발 > Spring' 카테고리의 다른 글
Spring MVC(세션 관리) (0) 2020.07.28 Spring MVC(폼 서블릿 오류 해결) (0) 2020.07.28 Spring MVC(html과의 매핑) (0) 2020.07.28 Spring MVC(요청 매개변수) (0) 2020.07.26 Spring MVC(URI 패턴) (0) 2020.07.26