사전 준비()
사전 준비 2 (테이블 생성)
CREATE TABLE WEB_TODO_CATEGORIES (
CATEGORY_NO NUMBER(3) PRIMARY KEY,
CATEGORY_NAME VARCHAR2(100) NOT NULL
);
INSERT INTO WEB_TODO_CATEGORIES VALUES(101, '프로젝트 기획');
INSERT INTO WEB_TODO_CATEGORIES VALUES(102, '요구사항 수집/분석');
INSERT INTO WEB_TODO_CATEGORIES VALUES(103, '시스템/애플리케이션 분석/설계');
INSERT INTO WEB_TODO_CATEGORIES VALUES(104, 'UI/UX 분석/설계');
INSERT INTO WEB_TODO_CATEGORIES VALUES(105, 'UI 디자인/구현');
INSERT INTO WEB_TODO_CATEGORIES VALUES(106, '애플리케이션 개발');
INSERT INTO WEB_TODO_CATEGORIES VALUES(107, '애플리케이션 테스트/배포');
INSERT INTO WEB_TODO_CATEGORIES VALUES(108, '애플리케이션 운영/유지보수');
CREATE TABLE WEB_TODOS (
TODO_NO NUMBER(4) CONSTRAINT WEB_TODO_NO_PK PRIMARY KEY,
TODO_CATEGORY_NO NUMBER(3) CONSTRAINT WEB_TODO_CATEGORY_NO_FK REFERENCES WEB_TODO_CATEGORIES (CATEGORY_NO),
TODO_TITLE VARCHAR2(255) NOT NULL,
TODO_USER_ID VARCHAR2(20) NOT NULL CONSTRAINT WEB_TODO_USER_ID_FK REFERENCES WEB_USERS (USER_ID),
TODO_BEGIN_DATE DATE NOT NULL,
TODO_END_DATE DATE NOT NULL,
TODO_COMPLETE_DATE DATE,
TODO_DESCRIPTION VARCHAR2(1000) NOT NULL,
TODO_STATUS VARCHAR2(100) DEFAULT '등록', -- 등록, 완료, 취소, 삭제, 연기 중 하나다.
TODO_CREATED_DATE DATE DEFAULT SYSDATE,
TODO_UPDATED_DATE DATE DEFAULT SYSDATE
);
CREATE TABLE WEB_TODO_WORKS(
WORK_NO NUMBER(4) CONSTRAINT WEB_WORK_NO_PK PRIMARY KEY,
WORK_USER_ID VARCHAR2(20) NOT NULL CONSTRAINT WEB_WORK_USER_ID_FK REFERENCES WEB_USERS (USER_ID),
WORK_CONTENT VARCHAR2(1000) NOT NULL,
WORK_CREATED_DATE DATE DEFAULT SYSDATE,
WORK_TODO_NO NUMBER(4) CONSTRAINT WEB_WORK_TODO_NO_FK REFERENCES WEB_TODOS (TODO_NO)
);
CREATE SEQUENCE WEB_TODOS_SEQ START WITH 1000 NOCACHE;
CREATE SEQUENCE WEB_WORKS_SEQ START WITH 1000 NOCACHE;
COMMIT;
TodoListController
package com.sample.app.controller.todo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sample.app.dao.TodoDao;
import com.sample.app.dto.TodoListDto;
import com.sample.model2.Controller;
import com.sample.util.Pagination;
import com.sample.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/*
* 요청 URI
* /todo/list.hta
* /todo/list.hta?page=2
* 요청파라미터
* page
* 반환값
* todo/list.jsp
* 요청처리 내용
* 요청파라미터에서 페이지번호를 조회한다.
* 총 데이터갯수를 조회한다.
* 페이징처리 처리를 위한 Pagination객체 생성
* 게시글 목록 조회범위를 계산해서 Map객체에 저장한다.
* PostDao의 getPosts(Map<String, Object> param) 메소드를 실행해서 게시글을 조회한다.
*
* 조회된 게시글목록을 요청객체의 속성으로 저장한다.
* 생성된 Pagination 객체를 요청객체의 속성으로 저장한다.
*
* 게시글 목록정보와 페이징정보를 표시하는 jsp 페이지를 반환한다
*/
public class TodoListController implements Controller {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 요청 파라미터값을 조회한다.
int currentPage = StringUtils.stringToInt(request.getParameter("page"), 1);
TodoDao todoDao = TodoDao.getInstance();
// 총 게시글 갯수를 조회하고, Pagination 객체를 생성한다.
int totalRows = todoDao.getTotalRows();
Pagination pagination = new Pagination(currentPage, totalRows);
// 게시글 목록 조회에 필요한 정보를 저장하는 Map 객체를 생성한다.
Map<String, Object> param = new HashMap<>();
param.put("begin", pagination.getBegin());
param.put("end", pagination.getEnd());
// TodoDao의 getTodos(Map<String, Object> param)메소드를 실행시켜서 게시글 목록을 조회한다.
List<TodoListDto> todoListDtos = todoDao.getTodos(param);
// 요청객체의 속성으로 게시글 목록정보를 저장한다.
request.setAttribute("todos", todoListDtos);
// 요청객체의 속성으로 페이징처리 정보를 저장한다.
request.setAttribute("pagination", pagination);
// 내부이동할 jsp 페이지를 반환한다.
return "todo/list.jsp";
}
}
Todo/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
<title>application</title>
</head>
<body>
<%@ include file="../common/navbar.jsp" %>
<div class="container my-3">
<div class="row mb-3">
<div class="col">
<h1 class="fs-4 border p-2 bg-light">할일 목록</h1>
</div>
</div>
<div class="row mb-3">
<div class="col">
<p>할일 목록을 확인하세요.
<c:if test="${not empty loginUserId }">
<a href="form.hta" class="btn btn-primary btn-sm float-end">새 할일 등록하기</a>
</c:if>
</p>
<table class="table table-sm">
<colgroup>
<col width="5%">
<col width="25%">
<col width="*">
<col width="6%">
<col width="5%">
<col width="8%">
<col width="8%">
<col width="8%">
</colgroup>
<thead>
<tr>
<th>번호</th>
<th>카테고리</th>
<th>제목</th>
<th class="text-center">작성자</th>
<th class="text-center">상태</th>
<th class="text-center">시작일</th>
<th class="text-center">종료일</th>
<th class="text-center">완료일</th>
</tr>
</thead>
<tbody class="small">
<c:choose>
<c:when test="${empty todos }">
<tr>
<td colspan="8" class="text-center">등록된 일정이 없습니다.</td>
</tr>
</c:when>
<c:otherwise>
<c:forEach var="dto" items="${todos }">
<tr>
<td>${dto.no }</td>
<td>${dto.categoryName }</td>
<td><a href="detail.hta?todoNo=${dto.no }" class="text-decoration-none">${dto.title }</a></td>
<td class="text-center">${dto.userName }</td>
<td class="text-center">${dto.status }</td>
<td class="text-center"><fmt:formatDate value="${dto.beginDate }" /></td>
<td class="text-center"><fmt:formatDate value="${dto.endDate }" /></td>
<td class="text-center"><fmt:formatDate value="${dto.completeDate }" /></td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
</tbody>
</table>
<c:if test="${pagination.totalRows > 0 }">
<nav>
<ul class="pagination pagination-sm justify-content-center">
<li class="page-item">
<a class="page-link ${pagiantion.first ? 'disabled' : '' }" href="list.hta?page=${pagination.prevPage }">이전</a>
</li>
<c:forEach var="number" begin="${pagination.beginPage }" end="${pagination.endPage }">
<li class="page-item">
<a class="page-link ${param.page == number ? 'active' : '' }" href="list.hta?page=${number }"> ${number }</a>
</li>
</c:forEach>
<li class="page-item">
<a class="page-link ${pagination.last ? 'disabled' : '' }" href="list.hta?page=${pagination.nextPage }">다음</a>
</li>
</ul>
</nav>
</c:if>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
</body>
</html>
실행 결과
TodoRegisterFormController
package com.sample.app.controller.todo;
import com.sample.model2.Controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
/*
* 요청 URI
* /todo/form.hta
* 요청 파라미터
* 없음
* 반환값
* todo/form.jsp
* redirect:app/user/loginform.hta?error=deny
* 요청처리 내용
* 세션에서 로그인된 사용자 정보를 조회한다.
* 사용자정보가 존재하지 않으면 로그인폼을 요청하는 재요청 URL("redirect:app/user/loginform.hta?error=deny")을 반환한다.
* 세션에 로그인된 사용자 정보가 존재하면 todo/form.jsp를 반환한다.
*/
public class TodoRegisterFormController implements Controller {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 세션에서 로그인된 사용자정보를 조회한다.
// 로그인된 사용자정보가 존재하지 않으면 로그인폼을 요청하는 재요청 URL을 반환한다.
HttpSession session = request.getSession();
if (session.getAttribute("loginUserId") == null) {
return "redirect:app/user/loginform.hta?error=deny";
}
// 세션에 로그인된 사용자 정보가 존재하면 todo/form.jsp를 반환한다.
return "todo/form.jsp";
}
}
Todo/form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css">
<title>application</title>
</head>
<body>
<%@ include file="../common/navbar.jsp" %>
<div class="container my-3">
<div class="row mb-3">
<div class="col">
<h1 class="fs-4 border p-2 bg-light">할일 등록폼</h1>
</div>
</div>
<div class="row mb-3">
<div class="col">
<p>새 할일을 등록하세요</p>
<form class="border bg-light p-3" method="post" action="register.hta">
<div class="mb-3">
<label class="form-label">카테고리</label>
<select class="form-select" name="categoryNo">
<option value="" selected="selected" disabled="disabled"> 카테고리를 선택하세요.</option>
<option value="101"> 프로젝트 기획</option>
<option value="102"> 요구사항 수집/분석</option>
<option value="103"> 시스템/애플리케이션 분석/설계</option>
<option value="104"> UI/UX 분석/설계</option>
<option value="105"> UI 디자인/구현</option>
<option value="106"> 애플리케이션 개발</option>
<option value="107"> 애플리케이션 테스트/배포</option>
<option value="108"> 애플리케이션 운영/유지보수</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">제목</label>
<input type="text" class="form-control" name="title" />
</div>
<div class="mb-3">
<label class="form-label">시작일</label>
<input type="date" class="form-control" name="beginDate" />
</div>
<div class="mb-3">
<label class="form-label">종료일</label>
<input type="date" class="form-control" name="endDate" />
</div>
<div class="mb-3">
<label class="form-label">설명</label>
<textarea rows="3" class="form-control" name="description"></textarea>
</div>
<div class="text-end">
<a href="list.hta" class="btn btn-secondary btn-sm">취소</a>
<button type="submit" class="btn btn-primary btn-sm">등록</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
</body>
</html>
실행결과
RegisterController
package com.sample.app.controller.todo;
import java.util.Date;
import com.sample.app.dao.TodoDao;
import com.sample.app.dto.TodoListDto;
import com.sample.app.vo.Todo;
import com.sample.model2.Controller;
import com.sample.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
/*
* 요청 URI
* /todo/register.hta
* 요청 파라미터
* title
* categoryNo
* beginDate
* endDate
* description
* 반환값
* redirect:/app/user/loginform.hta?fail=deny
* redirect:list.hta
* 요청처리 내용
* 로그인 상태가 아니면 재요청을 URL을 반환한다.
* 요청파라미터값(제목, 카테고리번호, 시작일, 종료일, 설명)을 조회한다.
* Todo객체를 생성해서 조회된 할일정보와 로그인한 사용자 아이디를 저장한다.
* TodoDao객체의 insertTodo(Todo todo)를 실행해서 할일 정보를 저장한다.
*
* 일정목록을 요청하는 재요청 URL을 응답으로 보낸다.
*/
public class TodoRegisterController implements Controller {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 세션에서 사용자 정보를 조회한다.
HttpSession session = request.getSession();
String loginUserId = (String) session.getAttribute("loginUserId");
if (loginUserId == null) {
return "redirect:/app/user/loginform.hta?fail=deny";
}
// 요청파라미터 값을 조회한다.
String title = request.getParameter("title");
int categoryNo = StringUtils.stringToInt(request.getParameter("categoryNo"));
Date beginDate = StringUtils.textToDate(request.getParameter("beginDate"));
Date endDate = StringUtils.textToDate(request.getParameter("endDate"));
String description = request.getParameter("description");
// Todo객체를 생성해서 할일 정보를 대입한다.
Todo todo = new Todo();
todo.setTitle(title);
todo.setUserId(loginUserId);
todo.setCategoryNo(categoryNo);
todo.setBeginDate(beginDate);
todo.setEndDate(endDate);
todo.setDescription(description);
// 할일 정보를 테이블에 저장시킨다.
TodoDao todoDao = TodoDao.getInstance();
todoDao.insertTodo(todo);
// 할일 목록을 요청하는 재요청 URL을 반환한다.
return "redirect:list.hta";
}
}
실행결과
구현 전
TodoDetailController