스프링 웹 MVC-27.DataBinder:@InitBinder, 예외 처리 핸들러:@ExceptionHandler


DataBinder: @InitBinder

특정 컨트롤러에서 바인딩 또는 검증 설정을 변경하고 싶을 때 사용

바인딩 설정

  • webDataBinder.setDisallowedFields();

포매터 설정

  • webDataBinder.addCustomFormatter();

Validator 설정

  • webDataBinder.addValidators();

특정 모델 객체에만 바인딩 또는 Validator 설정을 적용하고 싶은 경우

  • @InitBinder(“event”)

참고

  • https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-initbinder
  • https://github.com/spring-projects/spring-petclinic/blob/master/src/main/java/org/springframework/samples/petclinic/owner/PetController.java

바인딩 설정

@InitBinder
public void initEventBinder(WebDataBinder webDataBinder) {
    webDataBinder.setDisallowedFields("id"); // 모델에 안담긴다. 일반적으로 ID 값은 모델에 담기지 않고 생성할때 시퀸스
}

포매터 설정

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private LocalDate startDate;
    
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    private LocalDateTime startDateTime;

Validator 설정

    @InitBinder
    public void initEventBinder(WebDataBinder webDataBinder){
        webDataBinder.setDisallowedFields("id");
        webDataBinder.addValidators(new EventValidator());
    }
public class EventValidator implements Validator {

    // 어떠한 도메인 클래스에 대한 validate를 지원하는지 판단
    @Override
    public boolean supports(Class<?> clazz) {
        return Event.class.isAssignableFrom(clazz); // event 클래스 사용할때 validate
    }

    @Override
    public void validate(Object target, Errors errors) {
        Event event = (Event)target;
        /// name이 aaa 이면 에러 발생시킴
        if(event.getName().equalsIgnoreCase("aaa")){
            errors.rejectValue("name", "wrongValue", "the value is not allowed(aaa)");
        }
    }
}

혹은 특정 로직 또는 원하는 시점에만 validator을 적용하고 싶다면.

  1. EventValidator를 빈으로 등록하고
  2. EventValidator를 주입받아 원하는 시점에만 활용이 가능하다.
    @Component
    public class EventValidator implements Validator {
    
     @PostMapping(value = "/events/form/name")
     public String eventsFormNameSubmit(@Validated @ModelAttribute Event event,
                               BindingResult bindingResult) {
            
         // bindingResult.hasErrors() 보다 먼저 써야 에러에 반영
         eventValidator.validate(event, bindingResult); // 원하는 시점에만 validate 적용 가능
    
         if(bindingResult.hasErrors()){
             return "/events/form-name";
         }
    
         return "redirect:/events/form/age";
     }
    

예외 처리 핸들러: @ExceptionHandler

특정 예외가 발생한 요청을 처리하는 핸들러 정의

  • 지원하는 메소드 아규먼트 (해당 예외 객체, 핸들러 객체, …)
  • 지원하는 리턴 값
  • REST API의 경우 응답 본문에 에러에 대한 정보를 담아주고, 상태 코드를 설정하려면 ResponseEntity를 주로 사용한다.

참고

  • https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-exceptionhandler
  1. Exception 클래스
  2. ExceptionHandler
  3. throw 에러 ~~~java public class EventException extends RuntimeException{ }
    @ExceptionHandler
    public String eventErrorHandler(EventException exception, Model model, HandlerMethod method){
        System.out.println(method); // me.jaeuk.demowebmvc.SampleController#eventsFormName(Model) 출력
        model.addAttribute("message", "event error");
        return "error";
    }
    @GetMapping("/events/form/name")
    public String eventsFormName(Model model){
        throw new EventException(); // 임시 에러 테스트

        //model.addAttribute("event", new Event());
        //return "events/form-name";
    }

만약 여러개의 에러 익셉션을 사용할 경우?

    @ExceptionHandler({EventException.class, RuntimeException.class}) // 여러 개의 익셉션 사용 가능
    public String eventErrorHandler(RuntimeException ex, // 상위의 익셉션으로.
                                    Model model, 
                                    HandlerMethod method){
        System.out.println(method); // me.jaeuk.demowebmvc.SampleController#eventsFormName(Model) 출력
        model.addAttribute("message", "event error");
        return "error";
    }

본은으로 익셉션 반환

    @ExceptionHandler
    public ResponseEntity errorHandler(){
        return ResponseEntity.badRequest().body("can't create event as...");
    }





© 2019. by jaeuk