가입 일자
를 기준으로 검색하는 기능을 구현
// MemberDao.java
public class MemberDao {
...
public List<Member> selectByRegdate(LocalDateTime from, LocalDateTime to) {
List<Member> results = jdbcTemplate.query(
"select * from MEMBER where REGDATE between ? and ? " +
"order by REGDATE desc",
memRowMapper,
from, to);
return results;
}
}
selectRegDate()
매서드는 REGDATE 값이 두 파라미터로 전달받은 from
과 to
사이에 있는 Member 목록을 구함<input>
태그를 정의
<input type="text" name="from" />
<input type="text" name="to" />
LocalDateTime
타입으로 변환이 필요@DateTimeFormat
어노테이션을 적용해 다음처럼 변환
// ListCommand.java
public class ListCommand {
// 어노테이션을 적용하여 지정된 형식으로 변환
@DateTimeFormat(pattern = "yyyyMMddHH")
private LocalDateTime from;
@DateTimeFormat(pattern = "yyyyMMddHH")
private LocalDateTime to;
...
}
ListCommand
클래스를 커맨드 객체로 사용
// MemberListController.java
@Controller
public class MemberListController {
...
@RequestMapping("/members")
public String list(
@ModelAttribute("cmd") ListCommand listCommand,
Model model) {
// from과 to를 이용하여 member 목록을 구한 뒤, 뷰에 "members" 속성으로 전달
if (listCommand.getFrom() != null && listCommand.getTo() != null) {
List<Member> members = memberDao.selectByRegdate(
listCommand.getFrom(), listCommand.getTo());
model.addAttribute("members", members);
}
return "member/memberList";
}
}
Errors
타입 파라미터를 요청 어노테이션 적용 매서드에 추가
// MemberListController.java
@Controller
public class MemberListController {
...
@RequestMapping("/members")
public String list(
@ModelAttribute("cmd") ListCommand listCommand,
Errors errors, Model model) {
if (errors.hasErrors()) {
return "member/memberList";
}
if (listCommand.getFrom() != null && listCommand.getTo() != null) {
List<Member> members = memberDao.selectByRegdate(
listCommand.getFrom(), listCommand.getTo());
model.addAttribute("members", members);
}
return "member/memberList";
}
}
"typeMismatch"
를 추가하므로 다음처럼 메세지 프로퍼티 파일
을 통해 에러 메세지를 변경
가능
// label.properties
...
typeMismatch.java.time.LocalDateTime = 잘못된 형식
다음은 ID가 10인 회원의 정보를 조회하기 위한 URL
회원의 ID가 달라지면 경로의 마지막 부분이
달라짐
@PathVariable
어노테이션을 통해 가변 경로
처리 가능
// MemberDetailController.java
@Controller
public class MemberDetailController {
...
// {}중괄호에 둘러쌓인 부분이 경로 변수
@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";
}
...
}
익셉션 처리
를 하여 사용자에게 더 적합한 안내를 다음과 같이 제공
익셉션 처리를 해주지 않으면 HTTP Status 400 같은 페이지가 사용자에게 보임
- 컨트롤러에서 발생한 익셉션을 직접 처리하기 위해
@ExceptionHandler
어노테이션을 사용@ControllerAdvice
어노테이션을 이용해 공통 익셉션을 처리
@ExceptionHandler
어노테이션을 적용한 매서드가 존재하면 그 메서드가 익셉션을 처리
// MemberDetailController.java
@Controller
public class MemberDetailController {
...
@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";
}
}
다수
의 컨트롤러에서 동일
타입의 익셉션이 발생하는 경우 사용@ControllerAdvice
어노테이션이 적용된 클래스는 지정한 범위의 컨트롤러에 공통
으로 사용될 설정을 지정 가능@ControllerAdvice
어노테이션 적용 클래스가 동작하기 위해 해당 클래스를 스프링의 Bean으로 등록해야 함
// CommonExceptionHandler.java
// spring 패키지와 그 하위 패키지에 속한 컨트롤러 클래스를 위한 공통 기능을 정의
@ControllerAdvice("spring")
public class CommonExceptionHandler {
// 처리하는 익셉션의 종류는 RuntimeException
@ExceptionHandler(RuntimeException.class)
public String handleRuntimeException() {
return "error/commonException";
}
}
컨트롤러
클래스의 @ExceptionHandler 매서드가 우선함
순서
로 처리
같은 컨트롤러
에 위치한 @ExceptionHandler 매서드 중 해당 익셉션을 처리할 수 있는 매서드를 검색@ControllerAdvice
클래스에 위치한 @ExceptionHandler 매서드를 검색