스프링 MVC 핸들러 메소드 아규먼트에 사용할 수 있으며 validation group이라는 힌트를 사용할 수 있다. @Valid 애노테이션에는 그룹을 지정할 방법이 없다. @Validated는 스프링이 제공하는 애노테이션으로 그룹 클래스를 설정할 수 있다.
그룹 클래스를 명시하지 않고 @Validated만 붙이면 @Valid만 붙인 것과 동일하다.
@Controller
public class SampleController {
@GetMapping("/events/form")
public String eventsForm(Model model) {
Event newEvent = new Event();
newEvent.setLimit(50);
model.addAttribute("event", newEvent);
return "events/form";
}
@PostMapping("/events/name/{name}")
@ResponseBody
public Event createEvent(@ModelAttribute @Validated({Event.ValidateLimit.class, Event.ValidateName.class}) Event event, BindingResult bindingResult){
if(bindingResult.hasErrors()){
System.out.println("======================");
bindingResult.getAllErrors().forEach(c -> {
System.out.println(c.toString());
});
}
return event;
}
}
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 getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getLimit() {
return limit;
}
public void setLimit(Integer limit) {
this.limit = limit;
}
}
만약 @Validated에 Event.ValidateLimit.class만 지정해주면 Limit 데이터만 검증하고 Event.ValidateName.class만 지정하면 Name 데이터만 검증한다.
@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void eventForm() throws Exception{
mockMvc.perform(get("/events/form"))
.andDo(print())
.andExpect(view().name("/events/form"))
.andExpect(model().attributeExists("event"));
}
@Test
public void createEvent() throws Exception{
mockMvc.perform(post("/events/name/spring")
.param("limit", "-10"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value(spring));
}
}
참고