참고 도서 : 스프링5 프로그래밍 입문 - 최범균 저 |
ch14. MVC 4: 날짜 값 변환/@PathVariable/익셉션 처리
1. [프로젝트 준비]
-11, 12, 13장의 에제형식 그대로 사용
2. [날짜를 이용한 회원 검색 기능] : 회원 가입 일자 기준으로 검색 기능 구현
[회원 가입 일자 기준 ->회원 검색 기능 구현] MemberDao.java // + selectByRegdate() 메소드 추가 ListCommand.java //커맨드 객체 MemberListController.java //컨트롤러 클래스 memberList.jsp // 뷰 코드 |
▶<MemberDao .java> // selectByRegdate() 메소드 추가하기
public class MemberDao { //회원 정보 관리 클래스
//필드
private JdbcTemplate jdbcTemplate;
//Jdbc템플릿 = DB 연동 후 쿼리 .query() 메소드 제공하여 편리한 쿼리 사용 O
...
//추가한 메소드 selectByRegdate() 는 특정 날짜 기간 동안 가입한 회원 목록 List 반환 메소드
public List<Member> selectByRegdate(LocalDateTime from, LocalDateTime to) {
//from ~ to 날짜 사이에 존재하는 Member 목록을 구함
List<Member> results = jdbcTemplate.query(
"select * from MEMBER where REGDATE between ? and ? " +
"order by REGDATE desc",
memRowMapper,
from, to);
return results;
}
...
}
▶<ListCommand. java> //뷰 코드에 입력된 데이터 타입 변환해서 받아올 커맨드 객체
-> 검색 폼(뷰)에 입력된 날짜 문자열을 처리하기 위해서는 LocalDateTime 타입 변환 필요
public class ListCommand { //뷰 코드 데이터를 타입 변환하여 내부 필드에 받는 커맨드 객체
//필드
@DateTimeFormat(pattern = "yyyyMMddHH")
private LocalDateTime from;
@DateTimeFormat(pattern = "yyyyMMddHH")
private LocalDateTime to;
public LocalDateTime getFrom() {
return from;
}
public void setFrom(LocalDateTime from) {
this.from = from;
}
public LocalDateTime getTo() {
return to;
}
public void setTo(LocalDateTime to) {
this.to = to;
}
}
# 스프링은 String -> 기본 데이터 타입(Long/int 등) 으로의 타입 변환은 기본 처리 O String -> LocalDateTime 타입 변환 : 추가 설정 필요 -> 뷰코드 데이터를 받아올 커맨드 객체의 필드에 @DateTimeFormat 적용 |
▶▶ @DateTimeFormat : 커맨드 객체 데이터 타입 변환 처리 역할 -커맨드 객체 필드에 적용할 경우, 이 애노테이션의 pattern 속성값에 지정한 형식을 이용하여 뷰 코드에 입력된 문자열을 LocalDatetime 타입으로 변환한다. -이렇게 되면 컨트롤러 클래스에서 뷰 코드에 입력된 검색 요청을 처리할 때 따로 데이터 타입 변환 거치지 않고 커맨드 객체에서 변환된 데이터를 그대로 처리하면 된다. |
▶<MemberListController .java> //컨트롤러 클래스 (-> 새 컨트롤러는 빈 등록 필요)
@Controller
public class MemberListController { //컨트롤러
//필드
private MemberDao memberDao;
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
//요청 매핑 적용 메소드
@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);
//뷰에 여기서 구한 Member 목록을 members 속성으로 전달함
}
return "member/memberList";
}
}
-> 뷰 코드 폼에 사용자가 입력한 날짜 문자열 데이터는 커맨드 객체에서 LocalDateTime 타입으로 변환하여 받은 뒤 컨트롤러 클래스에서 커맨드 객체를 파라미터로 받는 구조이므로 해당 데이터를 요청에 맞게 내부적으로 처리할 수 있다. -> 컨트롤러 클래스 속 list() 메소드는 커맨드 객체로 받은 from, to 이용하여 해당 기간에 가입한 Member 목록을 구하여 반환하는데, 이와 동시에 Model 타입 model을 통해서 뷰에도 members 속성으로 Member 목록을 함께 전달한다. |
▶<memberList.jsp> //뷰 코드 작성
-뷰 코드는 컨트롤러 클래스의 list()가 전달해준 members 속성을 이용해서 회원 목록을 출력하도록 폼을 다시 구현
<!DOCTYPE html>
<html>
<head>
<title>회원 조회</title>
</head>
<body>
<form:form modelAttribute="cmd">
<p>
<label>from: <form:input path="from" /></label>
<form:errors path="from" />
~
<label>to:<form:input path="to" /></label>
<form:errors path="to" />
<input type="submit" value="조회">
</p>
</form:form>
<c:if test="${! empty members}">
<table>
<tr>
<th>아이디</th><th>이메일</th>
<th>이름</th><th>가입일</th>
</tr>
<c:forEach var="mem" items="${members}">
<tr>
<td>${mem.id}</td>
<td><a href="<c:url value="/members/${mem.id}"/>">
${mem.email}</a></td>
<td>${mem.name}</td>
<td><tf:formatDateTime value="${mem.registerDateTime }"
pattern="yyyy-MM-dd" /></td>
//이 pattern 형식에 맞춰서 해당 날짜 데이터 값을 출력한다.
</tr>
</c:forEach>
</table>
</c:if>
</body>
</html>
3. [변환 에러 처리]
-지정 형식에 맞지 않은 값을 폼에 입력한 뒤 실행하면 기본적으로 400 에러가 발생한다. -사용자 입장에선 400에러를 보는 것 보다 <<< 폼에 알맞은 에러 메시지를 보고 싶다. -에러 코드 : Errors 객체에 typeMismatch 에러 코드가 적용됨 -에러 코드에 알맞은 에러 메시지를 보여주고 싶을 때, 컨트롤러의 요청 매핑 메소드의 파라미터에 Errors 타입 파라미터를 추가하면 된다 -> * 단, Errors 파라미터는 반드시 커맨드 파라미터 바로 뒤에 위치해야 함 (원칙) -> 교재 p.335 설명. (원칙 어기면 Exception 발생) |
[메시지 프로퍼티 파일] <-해당 에러 코드 메시지 내용 작성
<label.properties> 파일
typeMismatch.java.time.LocalDateTime = 잘못된 형식 |
[뷰 코드] <- <form:errors> 태그 사용하여 해당 에러 메시지 내용 출력하는 코드 작성 추가
<memberList.jsp> 파일
4. [변환 처리에 대한 이해]
Q. @DateTimeFormat 애노테이션을 붙였을 때, 폼에 입력된 문자열을 누가 LocalDateTime 타입으로 변환해주는 건가 ? = WebDateBinder |
<WebDateBinder 의 역할>
▷값 타입 변환 관여
➀ 스프링 MVC는 요청 매핑 적용 메소드와 DispatcherServlet 사이 연결을 위해 RequestMappingHandlerAdapter 객체를 사용함 ➁ 이 핸들러 어댑터 객체는 다시, 요청 파라미터와 커맨드 객체 사이의 타입 변환 처리를 위해 WebDateBinder를 이용함 ➂ WebDateBinder는 커맨드 객체를 생성하고, 커맨드 객체의 프로퍼티와 같은 이름을 갖는 요청 파라미터를 이용해서 프로퍼티 값을 생성함 ➃ 단, WebDateBinder가 직접 타입 변환 X ConversionService에 타입 변환 역할을 위임 O |
--> 그래서 커맨드 클래스에 @DateTimeFormat 적용하면 지정 형식 문자열 타입으로 데이터를 받을 수 있게 되는 것
▷ <form:input> 태그에도 사용됨
-이 태그 path 속성에 지정한 프로퍼티 값을 String 값으로 변환하여 <input> 태그의 value 속성값으로 생성한다.
5. [중복 코드 정리 및 메소드 추가]
-객체 생성 코드가 중복이 생길 경우,
중복 제거를 위해 임의 객체를 필드로 할당한 뒤 해당 필드를 사용하여 간결하게 코드 작성O
6. [@PathVariable 이용 가변 경로 변수 처리]
ex. 형식 URL http://localhost:8080/sp5-chap14/members/10 |
-이 형식 URL 사용하면 각 회원마다 “members/{id}”에서 id 값이 달라진다.
* 경로 변수 : {중괄호}로 둘러쌓인 부분
-요청 경로에서 {id}에 해당하는 경로 값은 해당 요청 매핑 적용 메소드의 @PathVariable(“id”) 가 적용된 memID 파라미터에 전달한다. -이 경우 String으로 받았던 경로 값은 memID 해당 타입(Long)에 알맞게 변환됨 |
@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";
}
-> 이제 주소 입력할 때, @PathVariable을 통해 전달받은 경로 변수값을 이용해서 회원 정보를 읽어와 뷰에 결과를 전달할 수 있게 된다.
7. [컨트롤러 익셉션 처리]
▶ 컨트롤러 안에서 @ExceptionHandler 적용 메소드 구현
- 해당 컨트롤러 안에서 발생한 익셉션을 직접 처리함
각각의 @ExceptionHandler 메소드는 각 에러 내용 보여줄 뷰 이름 리턴함
▶ 컨트롤러 클래스에 @ExceptionHandler 적용 클래스
-해당 컨트롤러에서 발생한 익셉션만 처리함
▶ 컨트롤러 클래스에 @ControllerAdvice 적용 클래스
-多 여러 컨트롤러에서 동일 타입의 익셉션을 공통으로 처리함
-지정한 범위의 컨트롤러에 공통 사용될 설정 지정 가능
ex. @ControllerAdvice(“spring”) //spring 패키지 및 그 하위 패키지에 속한 컨트로로러 클래스들에 공통 적용됨 |
<우선 순위> : @ExceptionHandler 적용 클래스 > @ControllerAdvice 적용 클래스 @ExceptionHandler 클래스 안에 있는 @ExceptionHandler 메소드를 우선 처리한다. |
'Web(웹)_관련 공부 모음 > [개념]_스프링 5 프로그래밍' 카테고리의 다른 글
ch16. JSON 응답과 요청 처리 (0) | 2022.02.07 |
---|---|
ch15. 간단한 웹 어플리케이션 구조 (0) | 2022.02.03 |
ch13. MVC 3: 세션 /인터셉터 / 쿠키 (0) | 2022.02.02 |
ch 12. MVC 2: 메시지 / 커맨드 객체 검증 (0) | 2022.02.02 |
ch11. MVC 1: 요청 매핑/커맨드 객체/ 리다이렉트/ 폼 태그/모델 (0) | 2022.02.01 |