본문 바로가기

Servlet&JSP

Step02_DB (할일목록 todo 페이지 최종)

 

해당 내용은 이전 게시글들에서 이어지는 내용이다

2022.08.17 - [Servlet&JSP] - Step02_DB (예제 : 할일목록 todo 페이지, 꾸미기 전)

2022.08.17 - [Servlet&JSP] - Step02_DB (include 자주 사용하는 부분 jsp로 분리하기)

 

 

index.jsp

include에 분리해논 navbar, footer 사용

컨텍스트 경로 기재

bootstrap 캐러셀 인디케이터 사용

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>index.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</head>
<body >
	<%--
		포함 시킬 jsp 페이지의 위치를 page 요소의 값으로 넣어준다.
		/ 는 바로 webapp 폴더가 된다.
		이렇게 포함시키면 index.jsp 페이지와 navbar.jsp 페이지가 공동으로 클라이언트에게 응답을 하게 된다.
		
		포함시킬 페이지에 파라미터를 전달할 수 있다.
		
		thisPage 라는 파라미터 명으로 index 라는 문자열을 전달하는 방법은 아래와 같다
		
		<jsp:param value="index" name="thisPage"/>
	 --%>
	<jsp:include page="/include/navbar.jsp">
		<jsp:param value="index" name="thisPage"/>
	</jsp:include>
	
	<div class="container">
		<h1 style="margin-top:30px; font-size:20px;">인덱스 페이지</h1>
		<%--
			절대경로를 표시할때 컨텍스트 경로가 필요하긴 하지만
			컨텍스트 경로는 나중에 실제로 프로젝트가 끝나고 배포되는 시점에 변경되거나 제거될 예정이다.
			따라서 코딩할때 컨텍스트 경로를 실제로 코딩해 놓으면 나중에 제거하거나 변경할때 어려움이 예상된다.
			해결책은 jsp 페이지에서 context 경로가 필요하면 아래의 EL(Expression Language)을 이용해서 출력하면 된다.
		 --%>
		<p>컨텍스트 경로(프로젝트명) : <strong>${pageContext.request.contextPath }</strong></p>
		<p>컨텍스트 경로(프로젝트명) : <strong><%=request.getContextPath() %></strong></p>
		<ul>
			<li><a href="${pageContext.request.contextPath }/test/form.jsp">폼테스트</a></li>
		</ul>
		
		<div id="carouselExampleIndicators" class="carousel slide" data-bs-ride="true">
		  <!-- 케러셀 하단의 표시바 -->
		  <div class="carousel-indicators">
		    <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
		    <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="1" aria-label="Slide 2"></button>
		    <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="2" aria-label="Slide 3"></button>
		  </div>
		  <div class="carousel-inner">
		    <div class="carousel-item active">
		      <img src="${pageContext.request.contextPath }/images/top01.jpg" class="d-block w-100" alt="...">
		    </div>
		    <div class="carousel-item">
		      <img src="${pageContext.request.contextPath }/images/top02.jpg" class="d-block w-100" alt="...">
		    </div>
		    <div class="carousel-item">
		      <img src="${pageContext.request.contextPath }/images/top03.jpg" class="d-block w-100" alt="...">
		    </div>
		  </div>
		  <!-- 케러셀 좌우 버튼 -->
		  <button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="prev">
		    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
		    <span class="visually-hidden">Previous</span>
		  </button>
		  <button class="carousel-control-next" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="next">
		    <span class="carousel-control-next-icon" aria-hidden="true"></span>
		    <span class="visually-hidden">Next</span>
		  </button>
		</div>
	</div>
	
<%--
	협동 작업을 통해서 응답할 jsp 페이지가 어디에 있는지 page 속성의 값으로 지정을 해주면
	이 부분은 해당 jsp 페이지가 응답을 하게 된다.
 --%>
<jsp:include page="/include/footer.jsp"></jsp:include>


</body>
</html>

 

navbar와 footer는 분리해놓은 것을 가져와 사용하였다.

2022.08.17 - [Servlet&JSP] - Step02_DB (include 자주 사용하는 부분 jsp로 분리하기, 삼항연산자)

 

컨텍스트 경로를  나타내는 방법에 대하여도 작성하였다.

<p>컨텍스트 경로(프로젝트명) : <strong>${pageContext.request.contextPath }</strong></p>
<p>컨텍스트 경로(프로젝트명) : <strong><%=request.getContextPath() %></strong></p>

 

bootstrap에서 캐러셀 인디케이터를 가져와 사용하였다.

https://getbootstrap.kr/docs/5.0/components/carousel/

 

 

DbcpBean.java

package test.util;

import java.sql.Connection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
/*
 *  [ Data Base Connection Pool Bean ]
 *  - 최초 Connection 이 필요한 시점에 미리 Connection 여러개를 얻어내서 Connection Pool 에
 *    넣어 놓고 필요할때 가져다 쓰고 다 쓴다음 반납하는 구조로 사용한다.
 *    
 *  - Connection Pool 에서 Connection 한개를 가져오는 방법
 *  
 *    Connection conn=new DbcpBean().getConn();
 *    
 *  - 다 사용한 다음 반납하는 방법
 *  
 *    conn.close(); // close() 메소드를 호출하면 자동으로 Pool 에 반납된다.
 */
public class DbcpBean {
   //필드
   private Connection conn;
   
   //생성자
   public DbcpBean() {
      try {
         Context initContext = new InitialContext();
         Context envContext  = (Context)initContext.lookup("java:/comp/env");
         DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
         //리턴되는 Connection 객체를 필드에 저장하기
         conn = ds.getConnection();
         System.out.println("Connection 얻어오기 성공!");
      }catch(Exception e) {
         e.printStackTrace();
      }
   }
   
   //메소드
   public Connection getConn() {
      return conn;
   }
}

 

TodoDto.java

package test.todo.dto;

public class TodoDto {
	private int num;
	private String content;
	private String regdate;
	
	public TodoDto() {}

	public TodoDto(int num, String content, String regdate) {
		super();
		this.num = num;
		this.content = content;
		this.regdate = regdate;
	}

	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getRegdate() {
		return regdate;
	}

	public void setRegdate(String regdate) {
		this.regdate = regdate;
	}
	
	
}

 

TodoDao.java

 

package test.todo.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import test.member.dto.MemberDto;
import test.todo.dto.TodoDto;
import test.util.DbcpBean;

public class TodoDao {
	private static TodoDao dao;
	
	private TodoDao() {}
	
	public static TodoDao getInstance() {
      //만일 static 필드가 null 이면(최초로 getInstance() 메소드가 호출된 것이라면)
      if(dao==null) {
         //MemberDao 객체를 생성해서 static 필드에 저장한다.
         dao=new TodoDao();
      }
      //static 필드에 저장된 MemberDao 객체의 참조값을 리턴해 준다. 
      return dao;
   }
	
	public boolean insert(TodoDto dto) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		int updatedRowCount = 0;
		try {
			conn = new DbcpBean().getConn();
			//실행할 sql 문
			String sql="INSERT INTO todo"
			   		+ " (num, content, regdate)"
			   		+ " VALUES(todo_seq.NEXTVAL, ?, SYSDATE)";
			pstmt = conn.prepareStatement(sql);
			//? 값을 바인딩 할게 있으면 바인딩하기
			pstmt.setString(1, dto.getContent());
			//insert, update, delete 를 수행하고 변화된 row 의 갯수를 리턴 받기
			updatedRowCount = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e) {
			}
		}
		//변화된 row 의 갯수가 0 보다 크면 작업 성공
		if (updatedRowCount > 0) {
			return true;
		} else {//그렇지 않으면 작업 실패
			return false;
		}
	}
	
   public boolean delete(int num) {
	    Connection conn = null;
		PreparedStatement pstmt = null;
		int updatedRowCount = 0;
		try {
			conn = new DbcpBean().getConn();
			//실행할 sql 문
			String sql = "DELETE FROM todo"
					+ " WHERE num=?";
			pstmt = conn.prepareStatement(sql);
			//? 값을 바인딩 할게 있으면 바인딩하기
			pstmt.setInt(1, num);
			//insert, update, delete 를 수행하고 변화된 row 의 갯수를 리턴 받기
			updatedRowCount = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (Exception e) {
			}
		}
		//변화된 row 의 갯수가 0 보다 크면 작업 성공
		if (updatedRowCount > 0) {
			return true;
		} else {//그렇지 않으면 작업 실패
			return false;
		}
   }
   
   public boolean update(TodoDto dto) {
      Connection conn = null;
      PreparedStatement pstmt = null;
      int updatedRowCount = 0;
      try {
         conn = new DbcpBean().getConn();
         //실행할 sql 문
         String sql = "UPDATE todo"
               + " SET content=?"
               + " WHERE num=?";
         pstmt = conn.prepareStatement(sql);
         //? 값을 바인딩 할게 있으면 바인딩하기
         pstmt.setString(1, dto.getContent());
         pstmt.setInt(2, dto.getNum());
         //insert, update, delete 를 수행하고 변화되 row 의 갯수를 리턴 받기
         updatedRowCount = pstmt.executeUpdate();
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         try {
            if (pstmt != null)
               pstmt.close();
            if (conn != null)
               conn.close();
         } catch (Exception e) {
         }
      }
      //변화된 row 의 갯수가 0 보다 크면 작업 성공
      if (updatedRowCount > 0) {
         return true;
      } else {//그렇지 않으면 작업 실패
         return false;
      }
   }
   
   public TodoDto getData(int num) {
	   	  TodoDto dto=null;
	      Connection conn = null;
	      PreparedStatement pstmt = null;
	      ResultSet rs = null;
	      try {
	         //Connection 객체의 참조값 얻어오기 (Connection Pool 에서 하나 가져오기)
	         conn = new DbcpBean().getConn();
	         //실행할 sql 문 작성
	         String sql = "SELECT content, TO_CHAR(regdate,'YYYY.MM.DD HH24:MI') regdate"
	               + " FROM todo"
	               + " WHERE num=?";
	         //sql 문을 전달하면서 PreparedStatement 객체의 참조값 얻어오기
	         pstmt = conn.prepareStatement(sql);
	         //? 에 값을 바인딩 할게 있으면 한다.
	         pstmt.setInt(1, num);
	         //select 문 수행하고 결과를 ResultSet 으로 받아온다.
	         rs = pstmt.executeQuery();
	         //반복문 돌면서 ResultSet 의 cursor 를 한칸씩 내린다.
	         while (rs.next()) {
	            //cursor 가 위치한 곳의 칼럼 데이터 추출해서 어딘가에 담기 
	            dto=new TodoDto();
	            dto.setNum(num);
	            dto.setContent(rs.getString("content"));
	            dto.setRegdate(rs.getString("regdate"));
	         }

	      } catch (Exception e) {
	         //혹시 예외가 발생한다면 예외정보를 콘솔에 출력해서 에러의 원인 찾기 
	         e.printStackTrace();
	      } finally {
	         try {
	            if (rs != null)
	               rs.close();
	            if (pstmt != null)
	               pstmt.close();
	            if (conn != null)
	               conn.close(); //Connection 반납
	         } catch (Exception e) {
	         }
	      }
	      return dto;
	   }

	//전체 회원의 목록을 리턴하는 메소드 
	public List<TodoDto> getList(){
		  
		  //회원 목록을 담을 객체 생성
		  List<TodoDto> list=new ArrayList<>();
		   
	   Connection conn=null;
	   PreparedStatement pstmt=null;
	   ResultSet rs=null;
	   try {
	 	  //Connection 객체의 참조값 얻어오기 (Connection Pool 에서 하나 가져오기)
	 	  conn=new DbcpBean().getConn();
	 	  //실행할 sql 문 작성
	 	  String sql="SELECT num, content, TO_CHAR(regdate,'YYYY.MM.DD HH24:MI') regdate"
	 	  		+ " FROM todo"
	 	  		+ " ORDER BY num ASC";
	 	  //sql 문을 전달하면서 PreparedStatement 객체의 참조값 얻어오기
	 	  pstmt=conn.prepareStatement(sql);
	 	  //?에 값을 바인딩 할게 있으면 한다.
	 	  
	 	  //select 문 수행하고 결과를 ResultSet으로 받아온다.
	 	  rs=pstmt.executeQuery();
	 	  //반복문 돌면서 ResultSet의 cursor 를 한칸씩 내린다.
	 	  while(rs.next()) {
	 		  //cursor가 위치한 곳의 칼럼 데이터 추출해서 어딘가에 담기
	 		  
	 		  //TodoDto 객체를 생성해서
	 		  TodoDto dto=new TodoDto();
	 		  //ResultSet 에서 읽어온 정보를 MemberDto 객체의 setter 메소드를 이용해서 담는다.
	 		  dto.setNum(rs.getInt("num"));
	 		  dto.setContent(rs.getString("content"));
	 		  dto.setRegdate(rs.getString("regdate"));
	 		  //회원 한명의 정보를 담고 있는 MemberDto 객체의 참조값을 ArrayList 객체에 누적 시키기
	 		  list.add(dto);
	 	  }
	   }catch(Exception e) {
	 	  //혹시 예외가 발생한다면 예외정보를 콘솔에 출력해서 에러의 원인 찾기
	 	  e.printStackTrace();
	   }finally {
	 	  try {
	 		  if(rs!=null)rs.close();
	 		  if(pstmt!=null)pstmt.close();
	 		  if(conn!=null)conn.close(); //Connection 반납
	 	  }catch(Exception e) {}
	   }
	   //ArrayList 객체의 참조값 리턴하기
	   return list;
	}
}

 

/todo/list.jsp

문자열 bootstrap icon으로 대체

visually-hidden 코드 사용

<%@page import="test.todo.dto.TodoDto"%>
<%@page import="java.util.List"%>
<%@page import="test.todo.dao.TodoDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//MemberDao 객체의 참조값을 얻어와서
	TodoDao dao=TodoDao.getInstance();
	//회원목록을 얻어온다.
	List<TodoDto> list=dao.getList();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/todo/list.jsp</title>
<style>
#customers {
  font-family: Arial, Helvetica, sans-serif;
  border-collapse: collapse;
  width: 100%;
}

#customers td, #customers th {
  border: 1px solid #ddd;
  padding: 8px;
}

#customers tr:nth-child(even){background-color: #f2f2f2;}

#customers tr:hover {background-color: #ddd;}

#customers th {
  padding-top: 12px;
  padding-bottom: 12px;
  text-align: left;
  background-color: #04AA6D;
  color: white;
}
</style>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</head>
<body>
	<jsp:include page="/include/navbar.jsp">
		<jsp:param value="todo" name="thisPage"/>
	</jsp:include>
	
	<div class="container">
	<h1 style="margin:20px; font-size:20px; text-align:center;">할일 목록</h1>
		<table id="customers">
			<thead>
				<tr>
					<th>번호</th>
					<th>할일</th>
					<th>날짜</th>
					<th>수정</th>
					<th>삭제</th>
				</tr>
			</thead>
			<tbody>
			<%for(TodoDto tmp:list) {%>
				<tr>
					<td><%=tmp.getNum() %></td>
					<td><%=tmp.getContent() %></td>
					<td><%=tmp.getRegdate() %></td>
					<td>
						<a href="updateform.jsp?num=<%=tmp.getNum() %>">
							<span class="visually-hidden">수정</span>
							<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pencil-square" viewBox="0 0 16 16">
							  <path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/>
							  <path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z"/>
							</svg>
				   		</a>
					</td>
					<td>
						<a href="delete.jsp?num=<%=tmp.getNum() %>">
							<span class="visually-hidden">삭제</span>
							<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash3" viewBox="0 0 16 16">
							  <path d="M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5ZM11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H2.506a.58.58 0 0 0-.01 0H1.5a.5.5 0 0 0 0 1h.538l.853 10.66A2 2 0 0 0 4.885 16h6.23a2 2 0 0 0 1.994-1.84l.853-10.66h.538a.5.5 0 0 0 0-1h-.995a.59.59 0 0 0-.01 0H11Zm1.958 1-.846 10.58a1 1 0 0 1-.997.92h-6.23a1 1 0 0 1-.997-.92L3.042 3.5h9.916Zm-7.487 1a.5.5 0 0 1 .528.47l.5 8.5a.5.5 0 0 1-.998.06L5 5.03a.5.5 0 0 1 .47-.53Zm5.058 0a.5.5 0 0 1 .47.53l-.5 8.5a.5.5 0 1 1-.998-.06l.5-8.5a.5.5 0 0 1 .528-.47ZM8 4.5a.5.5 0 0 1 .5.5v8.5a.5.5 0 0 1-1 0V5a.5.5 0 0 1 .5-.5Z"/>
							</svg>
				   		</a>
					</td>
				</tr>
			<%} %>
			</tbody>
		</table>
		<br>
		<form action="insertform.jsp" method="post">
			<button type="submit" class="btn btn-outline-success">
				할일추가
		   		<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-workspace" viewBox="0 0 16 16" style="margin-bottom:2px;">
				  <path d="M4 16s-1 0-1-1 1-4 5-4 5 3 5 4-1 1-1 1H4Zm4-5.95a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z"/>
				  <path d="M2 1a2 2 0 0 0-2 2v9.5A1.5 1.5 0 0 0 1.5 14h.653a5.373 5.373 0 0 1 1.066-2H1V3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v9h-2.219c.554.654.89 1.373 1.066 2h.653a1.5 1.5 0 0 0 1.5-1.5V3a2 2 0 0 0-2-2H2Z"/>
				</svg>
			</button>
		</form>
	</div>
	
	<%--footer.jsp 포함시키기 --%>
	<jsp:include page="/include/footer.jsp"></jsp:include>
	
</body>
</html>

icon을 bootstrap으로 가져와 문자열 대신 넣었다. 이때 수정, 삭제 아이콘은 정상 작동하지만 문자열이 없기 때문에 시각장애인들을 위한 배려가 없다. 그래서 아래의 코드를 작성하여 눈에 보이지는 않지만 스크린 리더기에 읽히게 코드를 작성했다.

<span class="visually-hidden">수정</span>

 

 

/todo/insertform.jsp

breadcrump기능추가

form-floating 기능추가

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>insertform.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</head>
<body>
	
	<jsp:include page="/include/navbar.jsp">
		<jsp:param value="todo" name="thisPage"/>
	</jsp:include>
	
	<div class="container">
		<nav class="mt-2">
         <ol class="breadcrumb">
            <li class="breadcrumb-item">
               <a href="${pageContext.request.contextPath }/index.jsp">Home</a>
            </li>
            <li class="breadcrumb-item">
               <a href="${pageContext.request.contextPath }/todo/list.jsp">할일목록</a>
            </li>
            <li class="breadcrumb-item active">할일 추가 페이지</li>
         </ol>
      	</nav>
		<h1 style="margin:20px; font-size:20px; text-align:center;">할일 추가 폼 입니다.</h1>
		<form action="insert.jsp" method="post">
			<div class="form-floating mb-3">
				<input type="text" name="content" placeholder="할일입력" class="form-control" id="content" />
				<label for="content"  class="form-label">할일</label>
			</div>
			<button type="submit" class="btn btn-success btn-sm">추가</button>
		</form>
	</div>
	
	<jsp:include page="/include/footer.jsp"></jsp:include>
	
</body>
</html>

bootstrap에서 breadcrump라는 기능을 가져와서 현재 위치에 대해 확인 가능하게 코드를 작성했다.

form-floating 기능을 추가하여 회원목록 추가와 약간의 차이가 있다.

 

/todo/insert.jsp

 

<%@page import="test.todo.dao.TodoDao"%>
<%@page import="test.todo.dto.TodoDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
   //post 방식 전송 파라미터 추출할때 한글깨지지 않도록
   request.setCharacterEncoding("utf-8");

   //1. 폼 전송되는 title을 추출한다
   String content=request.getParameter("content");
   
   //MemberDto 객체에 회원 정보를 담고
   TodoDto dto=new TodoDto();
   dto.setContent(content);

   //2. DB 에 저장한다.
   TodoDao dao=TodoDao.getInstance();
   //MemberDao 객체를 이용해서 DB 에 저장을 하고 성공여부를 리턴 받는다.
   boolean isSuccess=dao.insert(dto);
   //3. 응답한다.
%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/todo/insert.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</head>
<body>
   <div class="container mt-5">
      <h1>알림</h1>
      <%if(isSuccess){ %>
         <p class="alert alert-success">
            <strong><%=content %></strong> 의 정보를 추가 했습니다.
            <a class="alert-link" href="list.jsp">확인</a>
         </p>
      <%}else{ %>
         <p class="alert alert-danger">
            할일 정보 추가 실패!
            <a class="alert-link" href="insertform.jsp">다시 입력</a>
         </p>
      <%} %>
   </div>
</body>
</html>

 

/todo/delete.jsp

 

<%@page import="test.todo.dao.TodoDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//1. get 방식 파라미터로 전달되는 삭제할 번호를 읽어온다.
	int num=Integer.parseInt(request.getParameter("num"));
	//2. DB 에서 해당 정보를 삭제한다
	boolean isSuccess=TodoDao.getInstance().delete(num);
	//3. 응답한다.
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/todo/delete.jsp</title>
</head>
<body>
	<%if (isSuccess){%>
		<script>
			alert("삭제 했습니다.");
			location.href="list.jsp";
		</script>
	<%}else{ %>
		<script>
			alert("삭제 실패!");
			location.href="list.jsp";	
		</script>
	<%} %>
</body>
</html>

 

/todo/updateform.jsp

 

<%@page import="test.todo.dto.TodoDto"%>
<%@page import="test.todo.dao.TodoDao"%>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//1. get 방식 파라미터로 전달되는 수정할 회원의 번호를 읽어온다.
	int num=Integer.parseInt(request.getParameter("num"));
	//2. DB에서 수정할 회원의 정보를 얻어온다.
	TodoDto dto=TodoDao.getInstance().getData(num);
	//3. 수정할 회원의 정보를 form 에 출력해서 응답한다.
%>
<!DOCTYPE html>
<html>
<head>
<style>
	label{margin-top:8px;}
</style>
<meta charset="UTF-8">
<title>/todo/updateform.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</head>
<body>
	
	<jsp:include page="/include/navbar.jsp">
		<jsp:param value="todo" name="thisPage"/>
	</jsp:include>
	
	<div class="container">
	  <nav class="mt-2">
         <ol class="breadcrumb">
            <li class="breadcrumb-item">
               <a href="${pageContext.request.contextPath }/index.jsp">Home</a>
            </li>
            <li class="breadcrumb-item">
               <a href="${pageContext.request.contextPath }/todo/list.jsp">할일목록</a>
            </li>
            <li class="breadcrumb-item active">할일 수정 페이지</li>
         </ol>
      </nav>
	   <h1 style="margin-top:20px; font-size:20px; text-align:center;">할일 수정 양식</h1>
	   <form action="update.jsp" method="post">
	      <input type="hidden" name="num" value="<%=num%>"/>
	      <div class="mb-3 row">
	         <label class="col-sm-2 col-form-label" for="num">번호</label>
	         <div class="col-sm-10">
	            <input type="text" id="num" value="<%=num%>" readonly class="form-control-plaintext"/>
	         </div>
	      </div>
	      <div class="mb-3 row">
	         <label class="col-sm-2 col-form-label" for="content">내용</label>
	         <div class="col-sm-10">
	            <input class="form-control" type="text" name="content" id="content" value="<%=dto.getContent()%>"/>
	         </div>
	      </div>
	      <div class="mb-3 row">
	         <label class="col-sm-2 col-form-label" for="regdate">등록일</label>
	         <div class="col-sm-10">
	            <input class="form-control" type="text" id="regdate" value="<%=dto.getRegdate()%>" disabled/>
	         </div>
	      </div>
	      <button class="btn btn-success btn-sm" type="submit">수정확인</button>
	      <button class="btn btn-danger btn-sm" type="reset">취소</button>
	   </form>
	</div>
	
	<jsp:include page="/include/footer.jsp"></jsp:include>
	
</body>
</html>

 

/todo/update.jsp

bootstrap modal 사용

 

<%@page import="test.todo.dao.TodoDao"%>
<%@page import="test.todo.dto.TodoDto"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
   //1. 폼전송되는 수정할 할일의 번호와 내용을 읽어와서
   request.setCharacterEncoding("utf-8");
   int num=Integer.parseInt(request.getParameter("num"));
   String content=request.getParameter("content");
   //2. DB 에 수정 반영하고
   TodoDto dto=new TodoDto();
   dto.setNum(num);
   dto.setContent(content);
   boolean isSuccess=TodoDao.getInstance().update(dto);
   //3. 응답하기
%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/todo/update.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</head>
<body>
<div class="container">
   <%if(isSuccess){ %>
      <div class="modal" tabindex="-1" id="myModal">
        <div class="modal-dialog">
          <div class="modal-content">
            <div class="modal-header">
              <h5 class="modal-title">알림</h5>
              <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
              <p>할일을 성공적으로 수정 했습니다.</p>
            </div>
            <div class="modal-footer">
              <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">확인</button>
            </div>
          </div>
        </div>
      </div>
      <script>
         //띄울 Modal 의 참조값(bootstrap 의 기능을 사용할수 있는) 얻어와서 
         const myModal = new bootstrap.Modal('#myModal');
         //Modal 을 함수를 호출해서 강제로 띄우기 
         myModal.show();
         
         //모달이 숨겨 졌을때 실행할 함수 등록하고 (모달이 숨겨지면 "hidden.bs.modal" 이벤트 발생)
         document.querySelector("#myModal")
         .addEventListener("hidden.bs.modal", function(){
            //모달이 숨겨지면 할일 목록 보기로 이동
            location.href="list.jsp";
         });
      </script>
   <%}else{ %>
      <h1>알림</h1>
      <p class="alert alert-danger">
         할일 수정 실패! <a class="alert-link" href="updateform.jsp?num=<%=num%>">다시 시도</a>
      </p>
   <%} %>
</div>
</body>
</html>

modal 기능을 사용하였기 때문에 회원 수정 형식과 차이가 있다.