ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DataBinder: @InitBinder
    SPRING/스프링 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에 이름을 지정하면 된다.

Designed by Tistory.