스프링 웹 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을 적용하고 싶다면.
- EventValidator를 빈으로 등록하고
- 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
- Exception 클래스
- ExceptionHandler
- 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...");
}