package controller;
import java.time.LocalDateTime;
import org.springframework.format.annotation.DateTimeFormat;
public class ListCommand {
@DateTimeFormat(pattern = "yyyyMMddHH")
private LocalDateTime from;
@DateTimeFormat(pattern = "yyyyMMddHH")
private LocalDateTime to;
}
@DateTimeFormat 어노테이션을 사용하면 지정한 형식의 문자열을 LocalDateTime타입으로 변환해주는 것은 WebDataBinder이다.
스프링 MVC는 요청 매핑 어노테이션 적용 메서드와 DispatcherServlet 사이를 연결하기 위해 RequestMappingHandlerAdapter 객체를 이용한다.
이 핸들러 어댑터 객체는 요청 파라미터와 커맨드 객체 사이의 변환 처리를 위해 WebDataBinder를 이용한다.
package controller;
import org.springframework.beans.TypeMismatchException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import spring.Member;
import spring.MemberDao;
import spring.MemberNotFoundException;
@Controller
public class MemberDetailController {
private MemberDao memberDao;
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
@GetMapping("/members/{id}")
public String detail(@PathVariable("id") Long memId, Model model) {
Member member = memberDao.selectById(memId);
if (member == null) {
throw new MemberNotFoundException();
}
model.addAttribute("member", member);
return "member/memberDetail";
}
}
ControllerConfig 설정 클래스에서 빈으로 등록한다.
@Bean
public MemberDetailController memberDetailController() {
MemberDetailController controller = new MemberDetailController();
controller.setMemberDao(memberDao);
return controller;
}
타입 변환 실패에 대한 에러 화면을 노출하고 싶을때
@ExceptionHandler 어노테이션 사용 예시
package controller;
import org.springframework.beans.TypeMismatchException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import spring.Member;
import spring.MemberDao;
import spring.MemberNotFoundException;
@Controller
public class MemberDetailController {
private MemberDao memberDao;
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
@GetMapping("/members/{id}")
public String detail(@PathVariable("id") Long memId, Model model) {
Member member = memberDao.selectById(memId);
if (member == null) {
throw new MemberNotFoundException();
}
model.addAttribute("member", member);
return "member/memberDetail";
}
@ExceptionHandler(TypeMismatchException.class)
public String handleTypeMismatchException() {
return "member/invalidId";
}
@ExceptionHandler(MemberNotFoundException.class)
public String handleNotFoundException() {
return "member/noMember";
}
}
컨트롤러 클래스에서 @ExceptionHandler 어노테이션을 적용하면 해당 컨트롤러에서 발생한 익셉션만 처리한다.
다수의 컨트롤러에서 동일 타입의 익셉션이 발생할 수도 있다. 이때 익셉션 처리 코드가 동일하다면 어떻게 해야 할까?
각 컨트롤러 클래스마다 익셉션 처리 메서드를 구현하는 것은 불필요한 코드 중복을 발생 시킨다.
여러 컨트롤러에서 동일하게 처리할 익셉션이 발생하면 @ControllerAdvice를 이용해서 중복을 제거할 수 있다.
package common;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice("spring")
public class CommonExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public String handleRuntimeException() {
return "error/commonException";
}
}
@ControllerAdvice 클래스에 있는 @ExceptionHandler 메서드와 컨트롤러 클래스에 있는 @ExceptionHandler 메서드 중 컨트롤러 클래스에 적용된 @ExceptionHanndler메서드가 우선한다.
@ControllerAdvice 어노테이션은 공통 설정을 적용할 컨트롤러 대상을 지정하기 위해 제공하는 속성
@ExceptionHandler 어노테이션을 붙인 메서드가 가지는 파라미터
리턴 가능한 타입