Ch13. MVC 4 : 날짜 값 변환
날짜를 이용한 회원 검색 기능, @DateTimeFormat
목표는 두 개의 날짜를 입력하면 그 사이에 가입한 회원들의 목록을 출력하는 것이다.
우선 MemberDao 클래스에 selectByRegdate() 메서드를 추가한다.
memberDao.java
// 날짜를 이용한 회원 검색
// REGDATE가 from과 to 사이인 member 목록 리턴
public List<Member> selectByRegdate(
LocalDateTime from, LocalDateTime to)
{
List<Member> results = jdbcTemplate.query(
"select * from MEMBER where REGDATE between ? and ? " +
"order by REGDATE desc",
new RowMapper<Member>()
{
@Override
public Member mapRow(ResultSet rs, int rowNum) throws SQLException
{
Member member = new Member(
rs.getString("EMAIL"),
rs.getString("PASSWORD"),
rs.getString("NAME"),
rs.getTimestamp("REGDATE").toLocalDateTime()
);
member.setId(rs.getLong("ID"));
return member;
}
}, from, to);
return results;
}
selectByRegdate() 메서드는 LocalDateTime형의 두 개의 날짜 데이터를 받고 쿼리를 이용해 DB에서 두 날짜 사이의 member의 목록을 리턴한다.
다음은 커맨드 객체다.
ListCommand.java
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;
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;
}
}
두 개의 필드 from,to에 @DateTimeFormat 애노테이션이 있다.
목표는 두 개의 날짜를 입력하면 그 사이에 가입한 회원들의 목록을 출력하는 것이라고 했는데 입력을 받을때 jsp 파일에서 <input> 태그를 이용해 날짜를 입력받을 것이다. 그러면 입력 받은 문자열을 LocalDateTime 형으로 변환 해야 하는데, 이때 사용하는 것이 @DateTimeFormat 애노테이션이다.
이렇게 커맨드 클래스의 LocalDateTime형 필드에 @DateTimeFormat 을 적용했다면, 컨트롤러에서는 그냥 해당 커맨드 객체를 사용하기만 하면 된다.
컨트롤러 클래스
MemberListController.java
package controller;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import spring.Member;
import spring.MemberDao;
@Controller
public class MemberListController
{
private MemberDao memberDao;
public void setMemberDao(MemberDao memberDao)
{
this.memberDao = memberDao;
}
@RequestMapping("/members")
public String list(@ModelAttribute("cmd") ListCommand listCommand, Model model)
{
if(listCommand.getFrom() != null && listCommand.getTo() != null)
{
List<Member> members = memberDao.selectByRegdate(listCommand.getFrom(), listCommand.getTo());
model.addAttribute("members", members);
}
return "member/memberList";
}
}
list() 메서드에서 커맨드 객체로 ListCommand를 사용하고 있다.
memberDao.selectByRegdate() 메서드의 파라미터로 커맨드 객체 listCommand에서 날짜 데이터를 갖고와서 전달한다.
이미 커맨드 객체의 @DateTimeFormat 에 의해 LocalDateTime으로 변환이 된 상태이므로 그냥 전달해도 된다.
ControllerConfig 설정 클래스에 관련 빈들을 추가한다.
ControllerConfig.java
package config;
// ...
@Configuration
public class ControllerConfig
{
// MemberConfig.java에서 빈 객체로 추가됨
// ...
@Autowired
private MemberDao memberDao;
// ...
@Bean
public MemberListController memberListController()
{
MemberListController controller = new MemberListController();
controller.setMemberDao(memberDao);
return controller;
}
}
LocalDateTime 값을 원하는 형식으로 출력해주는 커스텀 태그 파일.
formatDateTime.tag
<%@ tag body-content="empty" pageEncoding="utf-8" %>
<%@ tag import="java.time.format.DateTimeFormatter" %>
<%@ tag trimDirectiveWhitespaces="true" %>
<%@ attribute name="value" required="true"
type="java.time.temporal.TemporalAccessor" %>
<%@ attribute name="pattern" type="java.lang.String" %>
<%
if (pattern == null) pattern = "yyyy-MM-dd";
%>
<%= DateTimeFormatter.ofPattern(pattern).format(value) %>
뷰
memberList.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="tf" tagdir="/WEB-INF/tags" %>
<!DOCTYPE html>
<html>
<head>
<title>회원 조회</title>
</head>
<body>
<form:form modelAttribute="cmd">
<p>
<label>from:<form:input path="from" /></label>
~
<label>to:<form:input path="to" /></label>
<input type="submit" value="조회">
</p>
</form:form>
<%-- from,to 입력 하지 않았을때는 members 존재하지 않음 --%>
<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>
</tr>
</c:forEach>
</table>
</c:if>
</body>
</html>
우선 <form:form>, <form:imput> 를 이용해 사용자에게서 날짜 두개를 입력받는다.
입력 전에는 "member"이 존재하지 않기 때문에 테이블을 보여주지 않다가, 입력이 존재할때 테이블을 보여준다.
출처 : 스프링5 프로그래밍 입문 (최범균 저)