Java

2024.07.11 JSP 프로그래밍 기본 JSP와 MVC 패턴 Todo 프로젝트(3)

정훈5 2024. 7. 11. 08:48

 

TodoController

package com.tenco.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import com.tenco.model.TodoDAO;
import com.tenco.model.TodoDAOImpl;
import com.tenco.model.TodoDTO;
import com.tenco.model.UserDTO;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

//.../mvc/todo/xxx

@WebServlet("/todo/*")
public class TodoController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	private TodoDAO todoDAO;
       
    public TodoController() {
    	todoDAO = new TodoDAOImpl(); // 업 캐스팅 된 상태
    }
    
    // http://localhost:8080/mvc/todo/form
    // http://localhost:8080/mvc/todo/todoform (권장 x) (지금은 이거 사용)
    //  ex) http://localhost:8080/mvc/todo/formzzz 
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// 로그인 한 사용자만 접근을 허용하도록 설계
		HttpSession session = request.getSession();
		UserDTO principal = (UserDTO)session.getAttribute("principal"); // 다운캐스팅
		// 인증검사
		if(principal == null) {
			// 로그인을 안한 상태
			response.sendRedirect("/mvc/user/signIn?message=invalid");
			return;
		} 
		
		String action = request.getPathInfo();
		System.out.println("action 확인 : " +action);
		
		switch(action) {
		case "/todoForm":
			todoFormPage(request, response); // ctr + 1 번 클릭 후 메서드 생성
			break;
		
		case "/list":
			System.out.println("응답 이후 확인 ~~~~~");
			todoListPage(request, response, principal.getId()); // ctr + 1 번 클릭 후 메서드 생성
			break;
			
		case "/detail":
			todoDetailPage(request, response, principal.getId() ); // ctr + 1 번 클릭 후 메서드 생성
			// alt + shift + r : 이름수정
			break;
			
		case "/delete":
			// TODO 수정 예정  1번에 principalId 넣기 
			 deleteTodo(request, response, principal.getId()); // ctr + 1 번 클릭 후 메서드 생성
			break;
			
		default:
			response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404를 출력
			break;
		}
	}
	
	/**
	 * todo 삭제 기능
	 * @param request
	 * @param response
	 * @param principalId
	 * @throws IOException
	 */
	
	
	private void deleteTodo(HttpServletRequest request, HttpServletResponse response, int principalId) throws IOException {
		System.out.println("222222222222222222222   :   " +  request.getParameter("id"));
		try {
			int todoId = Integer.parseInt(request.getParameter("id"));
			 todoDAO.deleteTodo(todoId, principalId);
		} catch (Exception e) {
			System.out.println("xxxxxxxxxxxx");
			e.printStackTrace();
			//response.sendRedirect(request.getContextPath() + "/todo/list?error=invalid");
		}
		System.out.println("yyyyyyyyyyyyyyy");
		response.sendRedirect(request.getContextPath() + "/todo/list");
	}

	// 상세보기 화면
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	private void todoDetailPage(HttpServletRequest request, HttpServletResponse response, int principalId) throws IOException {
		// detail?id=8;
		try {
			// todo - pk - 1, 3, 5 (야스오)
			// todo - pk - 2, 4, 6 (홍길동)
			int todoId = Integer.parseInt(request.getParameter("id"));
			TodoDTO dto = todoDAO.getTodoById(todoId);
			
			if(dto.getUserId() == principalId) {
				// 상세보기 화면으로 이동
				request.setAttribute("todo", dto);
				request.getRequestDispatcher("/WEB-INF/views/todoDetail.jsp").forward(request, response);
			} else {
				// 권한이 없습니다 or 잘못된 접근입니다.
				response.setContentType("text/html");
				response.setCharacterEncoding("UTF-8");
				PrintWriter out = response.getWriter();
				out.println("<script> alert('권한이 없습니다.'); history.back(); </script>");
				// history.back(); 뒤로 돌아가기 
			}
			// dto(userId)
			
		} catch (Exception e) {
			response.sendRedirect(request.getContextPath() + "/todo/list?error=invaild");
		}	
	}

	// http://localhost:8080/mvc/todo/list
	/**
	 *  사용자별 todo 리스트 화면 이동
	 * @param request
	 * @param response
	 * @param principalId
	 * @throws IOException
	 * @throws ServletException
	 */
	private void todoListPage(HttpServletRequest request, HttpServletResponse response, int principalId) throws IOException, ServletException {
		
		// request.getPathInfo()  --> URL 요청에 있어 데이터 추출
		// request.getParameter() --> URL 요청에 있어 데이터 추출
		// request.getAttribute() --> 뷰를 내릴 속성에 값을 담아서 뷰로 내릴 때 사용
		
		 List<TodoDTO> list = todoDAO.getTodosByUserId(principalId);
		 request.setAttribute("list", list);
		
		 System.out.println("99999999999999999");
		// todoList.jsp 페이지로 내부에서 이동 처리
		request.getRequestDispatcher("/WEB-INF/views/todoList.jsp").forward(request, response);
		
		
	}

/*
 *  todo 작성 페이지 이동
 *  @param 
 */
	// http://localhost:8080/mvc/user/signIn
	private void todoFormPage(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		
		
		request.getRequestDispatcher("/WEB-INF/views/todoForm.jsp").forward(request, response);
	}


	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// todo 추가 예정
		HttpSession session = request.getSession(); // 사용자가 로그인 했는지 안했는지 확인
		UserDTO principal = (UserDTO)session.getAttribute("principal");
		if(principal == null) {
			response.sendRedirect(request.getContextPath() + "/user/siginIn?error=invaild");
			return;
		}
		
		String action = request.getPathInfo();
		System.out.println("action 확인 : " +action);
		switch(action) {
		case "/add":
			// TODO 수정 예정  1번에 principalId 넣기 
			addTodo(request, response, principal.getId()); // ctr + 1 번 클릭 후 메서드 생성
			break;
			
		case "/update":
			// TODO 수정 예정  1번에 principalId 넣기 
			updateTodo(request, response, principal.getId()); // ctr + 1 번 클릭 후 메서드 생성
			break;
			
		default:
			response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404를 출력
			break;
		}
		
	}
	/**
	 *  todo 수정 기능
	 * @param request
	 * @param response
	 * @param principalId - 세션 ID 값
	 * @throws IOException
	 */
	private void updateTodo(HttpServletRequest request, HttpServletResponse response, int principalId) throws IOException {
		
		try {
			int todoId = Integer.parseInt(request.getParameter("id"));
		//	System.out.println("todoId : " + todoId);
			
			String title = request.getParameter("title");
			String description = request.getParameter("description");
			String dueDate = request.getParameter("dueDate");
			
			// CheckBox는 여러개 선택 가능한 태그 : String[] 배열로 선언 했음 
			// 이번에 CheckBox 는 하나만 사용 중
			// 체크박스가 선택되지 않았으면 NULL 을 반환하고 체크가 되어있다면 "on" 문자열로 넘어온다.
			System.out.println("3333333 : "+request.getParameter("completed"));
			boolean completed = "on".equalsIgnoreCase(request.getParameter("completed"));
			System.out.println("completed : " + completed);
			// on 문자열이 대문자인지 소문자인지 상관없이 받아서 true false 확인
//			System.out.println("completed : " +completed);
			
			TodoDTO dto = TodoDTO.builder()
					.id(todoId)
					.userId(principalId)
					.title(title)
					.description(description)
					.dueDate(dueDate)
					.completed(String.valueOf(completed))
					.build();
			
		todoDAO.updateTodo(dto, principalId);
		
		} catch (Exception e) {
			response.setContentType("text/html");
			response.setCharacterEncoding("UTF-8");
			PrintWriter out = response.getWriter();
			out.println("<script> alert('잘못된 요청입니다.'); history.back(); </script>");
		}
		// list 화면 재 요청 처리
		response.sendRedirect(request.getContextPath() +"/todo/list");
		
	}

	/*
	 * 세션별 사용자 ToDo 등록 
	 * @param request
	 * @param response
	 * @param principalId : 세션에 담겨 있는 UserId 값
	 */
	private void addTodo(HttpServletRequest request, HttpServletResponse response, int principalId) throws IOException {
		
		String title = request.getParameter("title");
		String description = request.getParameter("description");
		String dueDate = request.getParameter("dueDate");
		
		// CheckBox는 여러개 선택 가능한 태그 : String[] 배열로 선언 했음 
		// 이번에 CheckBox 는 하나만 사용 중
		// 체크박스가 선택되지 않았으면 NULL 을 반환하고 체크가 되어있다면 "on" 문자열로 넘어온다.
		boolean completed = "on".equalsIgnoreCase(request.getParameter("completed"));
		// on 문자열이 대문자인지 소문자인지 상관없이 받아서 true false 확인
//		System.out.println("completed : " +completed);
		
		TodoDTO dto = TodoDTO.builder()
				.userId(principalId)
				.title(title)
				.description(description)
				.dueDate(dueDate)
				.completed(String.valueOf(completed))
				.build();
				
		todoDAO.addTodo(dto, principalId);
		
		response.sendRedirect(request.getContextPath() + "/todo/list");	
		
	}

}

 

todoList.jsp

<%@page import="java.util.Date"%>
<%@page import="com.tenco.model.TodoDTO"%>
<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>할 일 목록</title>
<link rel="stylesheet" type="text/css" href="../css/style.css">
</head>
<body>
	<!--  http://localhost:8080/mvc/todo/todoList.jsp -->
	<!--  http://localhost:8080/mvc/user/signIn <-- 여기서 부터 시작 -->
	<!--  http://localhost:8080/mvc/todo/list -->

	<%
	
	List<TodoDTO> todoList = (List<TodoDTO>)request.getAttribute("list");
	
	// out.print("todoList " + todoList);
    // out.print(todoList.toString());
    
	if (todoList != null && !todoList.isEmpty()) {
	%>

	<h2>할 일 목록</h2>
	<a href="todoForm"> 새 할일 추가 </a>

	<table border="1">
		<tr>
			<th>제목</th>
			<th>설명</th>
			<th>마감일</th>
			<th>완료여부</th>
			<th>(액션-버튼)</th>
		</tr>
		<%
		for (TodoDTO todo : todoList) {
		%>
		<tr>
			<td><%=todo.getTitle()%></td>
			<td><%=todo.getDescription()%></td>
			<td><%=todo.getDueDate()%></td>
			<td><%=todo.completedToString() == "true" ? "완료" : "미완료"%></td>
			<td><a href="detail?id=<%=todo.getId()%>">상세보기</a> <!--  삭제 기능 -->
				<form action="delete" method="get">
					<input type="hidden" name="id" value="<%=todo.getId()%>">
					<button type="submit">삭제</button>
				</form></td>
		</tr>
		<%
		}
		%>

	</table>

	<%
	} else {
	%>

		<hr>
		<p>등록된 할 일이 없습니다.</p>
	
	<%
	}
	%>

</body>
</html>

 

TodoDAO

package com.tenco.model;

import java.util.List;

public interface TodoDAO {
	
	// 저장 기능 
	void addTodo(TodoDTO dto, int principalId);
	TodoDTO getTodoById(int id);
	
	// 사용자 아이디 기준으로 출력 todoList를 뽑는다.
	List<TodoDTO> getTodosByUserId(int userId);
	
	// 전체 리스트 출력
	List<TodoDTO> getALLTodos();
	
	// 사용자 글 업데이트
	void updateTodo(TodoDTO dto, int principalId);
	
	// 사용자 글 삭제
	void deleteTodo(int id, int principalId);

}

 

TodoDAOImpl

package com.tenco.model;

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

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class TodoDAOImpl implements TodoDAO {

	private DataSource dataSource;

	public TodoDAOImpl() {
		InitialContext ctx;
		try {
			ctx = new InitialContext();
			dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/MyDB");
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void addTodo(TodoDTO dto, int principalId) {
		// sql 작업할 때
		String sql = " insert into todos(user_id, title, description, due_date, completed)" + "values(?, ?, ?, ?, ?) ";

		try (Connection conn = dataSource.getConnection()) {
			conn.setAutoCommit(false); // 자동 커밋 x 내가 직접 커밋한다.

			try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
				pstmt.setInt(1, principalId);
				pstmt.setString(2, dto.getTitle());
				pstmt.setString(3, dto.getDescription());
				pstmt.setString(4, dto.getDueDate()); // TodoDTO의 util을 sql로 변경
				// if(dto.getCompleted() == "true") {}
				pstmt.setInt(5, dto.getCompleted() == "true" ? 1 : 0);
				pstmt.executeUpdate();
				conn.commit(); // 커밋

			} catch (Exception e) {
				e.printStackTrace();
				conn.rollback();
			}

		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}

	}

	@Override
	public TodoDTO getTodoById(int id) {

		String sql = " SELECT * FROM todos WHERE id = ? ";
		TodoDTO dto = null;

		try (Connection conn = dataSource.getConnection();) {

			PreparedStatement pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, id);

			try (ResultSet rs = pstmt.executeQuery()) {

				if (rs.next()) {
					dto = new TodoDTO();
					dto.setId(rs.getInt("id"));
					dto.setUserId(rs.getInt("user_id"));
					dto.setTitle(rs.getString("title"));
					dto.setDescription(rs.getString("description"));
					dto.setDueDate(rs.getString("due_date"));
					dto.setCompleted(rs.getString("Completed"));
				}

			} catch (Exception e) {
				e.printStackTrace();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return dto;
	} // end of getTodoById()

	// ------------------------------------------------

	@Override
	public List<TodoDTO> getTodosByUserId(int userId) {

		String sql = " SELECT * FROM todos WHERE user_id = ? ";
		List<TodoDTO> todos = new ArrayList<TodoDTO>();

		try {
			Connection conn = dataSource.getConnection();
			PreparedStatement pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, userId);

			try (ResultSet rs = pstmt.executeQuery();) {

				while (rs.next()) {
					TodoDTO dto = new TodoDTO(); // 메모리에 객체가 올라가야 사용할 수 있다.
					dto.setId(rs.getInt("id")); // db의 속성에 맞게 적어야 한다.
					dto.setUserId(rs.getInt("user_id"));
					dto.setTitle(rs.getString("title"));
					dto.setDescription(rs.getString("description"));
					dto.setDueDate(rs.getString("due_date"));
					dto.setCompleted(rs.getString("completed"));
					todos.add(dto);
				}

			} catch (Exception e) {
				// TODO: handle exception
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}

		return todos;
	} // end of getTodosByUserId()

	@Override
	public List<TodoDTO> getALLTodos() {
		// List는 인터페이스 이다.
		// List는 자신에게 맞는 구현클래스를 사용할수 있기에 ex) arrayList나 다른 리스트 등을 쓴다.
		String sql = " SELECT * FROM todos ";
		List<TodoDTO> todos = new ArrayList<TodoDTO>();

		try {
			Connection conn = dataSource.getConnection();
			PreparedStatement pstmt = conn.prepareStatement(sql);

			try (ResultSet rs = pstmt.executeQuery();) {

				while (rs.next()) {
					TodoDTO dto = new TodoDTO(); // 메모리에 객체가 올라가야 사용할 수 있다.
					dto.setId(rs.getInt("id")); // db의 속성에 맞게 적어야 한다.
					dto.setUserId(rs.getInt("user_id"));
					dto.setTitle(rs.getString("title"));
					dto.setDescription(rs.getString("description"));
					dto.setDueDate(rs.getString("due_date"));
					dto.setCompleted(rs.getString("completed"));
					todos.add(dto);
				}

			} catch (Exception e) {
				// TODO: handle exception
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}

		return todos;
	} // end of getALLTodos()

	@Override
	public void updateTodo(TodoDTO dto, int principalId) {

		// SELECT <-- 있지 없지 확인 과정 (필요)


		String sql = " UPDATE todos SET title = ?, description = ? " + " 				, due_date = ?, completed = ? "
				+ "    WHERE id = ? and user_id = ? ";
		try (Connection conn = dataSource.getConnection()) {
			conn.setAutoCommit(false);
			try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
				pstmt.setString(1, dto.getTitle());
				pstmt.setString(2, dto.getDescription());
				pstmt.setString(3, dto.getDueDate());
				pstmt.setInt(4, dto.getCompleted() == "true" ? 1 : 0);
				pstmt.setInt(5, dto.getId());
				pstmt.setInt(6, dto.getUserId());
				pstmt.executeUpdate();
				conn.commit();
			} catch (Exception e) {
				conn.rollback();
				e.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	} // end of updateTodo()

	@Override
	public void deleteTodo(int id, int principalId) {

		String sql = "delete from todos where id = ? and user_id = ? ";

		try (Connection conn = dataSource.getConnection();) {
			conn.setAutoCommit(false);

			try (PreparedStatement pstmt = conn.prepareStatement(sql)) {

				pstmt.setInt(1, id);
				pstmt.setInt(2, principalId);
				pstmt.executeUpdate();

				conn.commit();

			} catch (Exception e) {
				conn.rollback();
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}
	} // end of deleteTodo()

}

 

todoDetail.jsp

<%@page import="com.tenco.model.TodoDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상세보기 화면</title>
</head>
<body>
	<h2>상세 보기</h2>
	<%
		TodoDTO todo = (TodoDTO)request.getAttribute("todo");
		if(todo != null) {
	%>
			
		<p>제목 : <%=todo.getTitle() %></p><br>
		<p>설명 : <%=todo.getDescription() %></p><br>		
		<p>마감일 : <%=todo.getDueDate() %></p><br>		
		<p>완료여부 : <%=todo.completedToString() == "true" ? "완료" : "미완료" %></p><br>		
		<hr><br>
		<form action="update" method="post">
			<input type="hidden" name="id" value="<%=todo.getId()%>">
			<label for="title">제목 : </label>
			<input type="text" id="title" name="title" value="<%=todo.getTitle()%>">
			<br>
			<label for="description">설명 : </label>
			<input type="text" id="description" name="description" value="<%=todo.getDescription()%>">
			<br>
			<label for="dueDate">마감일 : </label>
			<input type="date" id="dueDate" name="dueDate" value="<%=todo.getDueDate()%>">
			<br>
			<label for="completed">완료여부 : </label>
			<input type="checkbox" id="completed" name="completed"  <%= todo.completedToString() == "true" ? "checked" : ""%> >
			<br>
			<button type="submit">수정</button>
		</form>		
			
	<%
		} else {
			out.print("<p> 정보를 불러오는데 실패 </p>");
		}
	%>
</body>
</html>