-
DataBinder: @InitBinderSPRING/스프링 MVC 2021. 7. 11. 16:33
특정 컨트롤러에서 바인딩 또는 검증 설정을 변경하고 싶을 때 사용
@InitBinder public void initEventBinder(WebDataBinder webDataBinder) { webDataBinder.setDisallowedFields("id"); }
바인딩 설정
- webDataBinder.setDisallowedFields();
포매터 설정
- webDataBinder.addCustomFormatter();
Validator 설정
- webDataBinder.addValidators();
특정 모델 객체에만 바인딩 또는 Validator 설정을 적용하고 싶은 경우
- @InitBinder(“event”)
@Controller @SessionAttributes("event") public class SampleController2 { // 특정 컨트롤러에서 바인딩 또는 검증 설정을 변경하고 싶을 때 사용 @InitBinder public void initEventBinder(WebDataBinder webDataBinder) { webDataBinder.setDisallowedFields("id"); } // 이름 Form 화면 @GetMapping("/events/form/name") public String eventsForm(Model model, HttpSession httpSession) { model.addAttribute("event",new Event()); return "/events/form-name"; } // 이름 form에서 입력받은 내용 전송 @PostMapping("/events/form/name") public String eventForNameSubmit(@ModelAttribute @Validated(Event.ValidateName.class) Event event, BindingResult bindingResult, Model model, SessionStatus sessionStatus) { // @Validated 어노테이션을 통하여 Validation 체크에 맞지 않으면 다시 form으로 리턴 if(bindingResult.hasErrors()) { return "/events/form-name"; } // POST-REDIRECT-GET 패턴 // ( Post 이후에 브라우저를 리프래시 하더라도 폼 서브밋이 발생하지 않도록 하는 패턴) return "redirect:/events/form/limit"; } // limit Form 화면 @GetMapping("/events/form/limit") public String eventForLimit(@ModelAttribute Event event, Model model) { model.addAttribute("event",event); return "events/form-limit"; } // limit form에서 입력받은 내용 전송 @PostMapping("/events/form/limit") public String eventForLimitSubmit(@ModelAttribute @Validated(Event.ValidateLimit.class) Event event, BindingResult bindingResult, RedirectAttributes attributes, SessionStatus sessionStatus) { if(bindingResult.hasErrors()) { return "/events/form-limit"; } // 세션 데이터 초기화 sessionStatus.setComplete(); attributes.addFlashAttribute("newEvent",event); return "redirect:/events/list"; } // 이벤트 목록 페이지 @GetMapping("/events/list") public String getEvents( Model model, @SessionAttribute LocalDateTime visitTime) { System.out.println(visitTime); // 리스트를 불러오는 부분 Event event = new Event(); event.setName("spring"); event.setLimit(10); Event newEvent = (Event) model.asMap().get("newEvent"); List<Event> eventList = new ArrayList<>(); eventList.add(event); eventList.add(newEvent); model.addAttribute(eventList); return "/events/list"; } //ModelAttribute 또다른 용번 // @Controller 또는 @ControllerAdvice를 사용한 클래에스 모델 정보를 초기화할 때 사용한다. @ModelAttribute() public void categories(Model model) { model.addAttribute("categories",List.of("study", "seminar","hobby","social")); } }
<!doctype html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Create New Event</title> </head> <body> <form action="#" th:action="@{/events/form/name}" method="post" th:object="${event}"> <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect limit</p> id : <input type="text" title="id" th:field="*{id}"> name : <input type="text" title="name" th:field="*{name}"> <input type="submit" value="Create"/> </form> </body> </html>
webDataBinder.setDisallowedFields("id");를 통하여 id값을 Model 객체에서 받지 않도록 설정하면 위와 같이 id값을 Model에서 받지 않는다.
public class Event { interface ValidateName {}; interface ValidateLimit {}; private int id; @NotBlank(groups=ValidateName.class) private String name; @Min(value = 30, groups=ValidateLimit.class) private int limit; // Formatter를 통한 String -> LocalTime 바인딩 @DateTimeFormat(iso= DateTimeFormat.ISO.DATE) private LocalDate startDate; public LocalDate getStartDate() { return startDate; } public void setStartDate(LocalDate startDate) { this.startDate = startDate; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getLimit() { return limit; } public void setLimit(int limit) { this.limit = limit; } }
<!doctype html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Create New Event</title> </head> <body> <form action="#" th:action="@{/events/form/name}" method="post" th:object="${event}"> <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect limit</p> id : <input type="text" title="id" th:field="*{id}"> Local Date : <input type="text" title="startDate" th:field="*{startDate}"> name : <input type="text" title="name" th:field="*{name}"> <input type="submit" value="Create"/> </form> </body> </html>
-> Formatter가 기본으로 등록되어 있어서 String이 LocalDate로 자동으로 바인딩된다.
즉, startDate에 2019-03-15 와 같은 문자열을 입력하여 submit하면 정상적으로 LocalDate 타입으로 바인딩된다.
public class EventValidator implements Validator { @Override public boolean supports(Class<?> aClass) { return Event.class.isAssignableFrom(aClass); } @Override public void validate(Object o, Errors errors) { Event event = (Event) o; // event name 문자열이 aaa 일때 Validation reject 처리한다. (대소문자상관없이) if (event.getName().equalsIgnoreCase("aaa")){ errors.rejectValue("name", "wrongValue", "the value is not allowed"); } } }
위와 같이 Validator를 생성하여 initBinder에 추가를 하면 Validator 속성을 클래스에 적용할 수 있다.
// 특정 컨트롤러에서 바인딩 또는 검증 설정을 변경하고 싶을 때 사용 @InitBinder public void initEventBinder(WebDataBinder webDataBinder) { webDataBinder.setDisallowedFields("id"); // EventValidator 속성 추가 webDataBinder.addValidators(new EventValidator()); }
클래스에서 aaa라는 이름을 받고 싶지 않다면 위와같이 EventValidator를 initBinder에 추가하면 된다.
// 특정 컨트롤러에서 바인딩 또는 검증 설정을 변경하고 싶을 때 사용 @InitBinder("evnet") public void initEventBinder(WebDataBinder webDataBinder) { webDataBinder.setDisallowedFields("id"); // EventValidator 속성 추가 webDataBinder.addValidators(new EventValidator()); }
또한 특정 모델 객체에만 바인딩 또는 Validator 설정을 적용하고 싶은 경우 이름을 @InitBinder에 이름을 지정하면 된다.
'SPRING > 스프링 MVC' 카테고리의 다른 글
전역 컨트롤러: @(Rest)ControllerAdvice (0) 2021.07.13 예외 처리 핸들러: @ExceptionHandler (0) 2021.07.13 모델: @ModelAttribute 또 다른 사용법 (0) 2021.07.11 핸들러 메소드 16부 - @ResponseBody & ResponseEntity (0) 2021.07.10 핸들러 메소드 15부: @RequestBody & HttpEntity (0) 2021.07.10