JSP서블릿 10일차

하파타카·2022년 1월 24일
0

JSP서블릿 수업

목록 보기
8/10
post-thumbnail

한 일

  • Todo App -3-
  • 기본페이지, user정보, message 세션>리퀘스트 수정
  • todo-list.jsp 페이지 만들기
  • 할일 리스트를 todo-list페이지에 동적 데이터로 받아 테이블로 입력
  • 할일 추가/수정

Todo App 만들기 -3-

기본페이지, user정보, message 세션>리퀘스트 수정

기본페이지 수정

-web.xml-

<welcome-file-list>
  <welcome-file>login/login.jsp</welcome-file>
</welcome-file-list>

-LoginController.java(서블릿)-

@WebServlet("/login")

user정보, message 세션에서 리퀘스트로 수정

  • 세션은 기본적으로 유저 로그인정보(로그인 실패시 id를 저장하고 실패메시지를 띄워줌)를 저장하기엔 기본적으로 서버에 저장되는 시간이 길기때문에 리퀘스트에 저장하도록 수정한다.

-LoginController.java(서블릿) doGet메서드-

// send는 페이지 새로열기이므로 모든 입력데이터가 사라짐
// login폴더 안의 login.jsp로 이동. forward가 아니라 단순히 페이지만 이동함
response.sendRedirect("login/login.jsp");

-LoginController.java(서블릿) doPost메서드-

request.setCharacterEncoding("UTF-8"); // 입력받을 때 한글설정
response.setContentType("text/html;charset=UTF-8");	// 출력할 때 한글설정
// id, password를 parameter로 입력받기
String username = request.getParameter("username");
String password = request.getParameter("password");
LoginBean loginBean = new LoginBean();
loginBean.setUsername(username);
loginBean.setPassword(password);

// 로그인이 성공했는지 체크
if (loginDao.validate(loginBean)) {	// true면 계정있음. 로그인됨 => 할일 페이지로 forward
	System.out.println("로그인 성공~!");
	RequestDispatcher dispatcher = request.getRequestDispatcher("todo/todo-list.jsp");
	dispatcher.forward(request, response);
}else { // false면 계정없음. 로그인 실패
	System.out.println("로그인 실패...");
	request.setAttribute("user", username);		// username은  request에 저장해 다시 보내줌 (비밀번호만 틀렸을때 재입력이 편하게)
	request.setAttribute("message", "Login Fail 로그인에 실패했습니다...");
	// 로그인 실패 내용을 forward로 다시 로그인 페이지에 보여주기(forward를 안해주면 리퀘스트는 새로고침할때 사라짐)
	RequestDispatcher dispatcher = request.getRequestDispatcher("login/login.jsp");
	dispatcher.forward(request, response);

todo-list.jsp 페이지 만들기

로그인 후 할일 목록을 보여줄 페이지.
우선 액션은 제외하고 나머지만 만들어줌.

-todo/todo-list.jsp-

<div class="container">
  <div class="row mt-5">
    <h3 class="text-center">할일 목록들</h3>
    <hr />
    <div class="container text-left">
      <a href="<%=request.getContextPath()%>/todos?action=new" class="btn btn-success">할일 추가</a>
    </div>
    <br />
    <table class="table table-bordered mt-3">
      <thead>
        <tr>
          <th>제목</th>
          <th>마감 일자</th>
          <th>현재 상태</th>
          <th>액션</th>
        </tr>
      </thead>
      <tbody>
        <!-- 동적 데이터(할일 데이터)를 테이블로 입력 -->
        <!-- 한 개의 할일을 변수todo에 저장 -->
        <c:forEach var="todo" items="${listTodo}">
          <tr>
            <td><c:out value="${todo.title}" /></td>
            <td><c:out value="${todo.targetDate}" /></td>
            <td><c:out value="${todo.status}" /></td>
            <td><!-- 액션 데이터가 들어갈 자리 --></td>
          </tr>
        </c:forEach>
      </tbody>
    </table>
  </div>
</div>

할일 리스트를 todo-list페이지에 받아 테이블로 입력

할일 리스트에서 받아온 정보(title, username, description, target_date, is_done)를 동적 데이터로 받아 todo-list페이지의 테이블로 입력함.
여기서 할일 리스트의 데이터는 갯수가 유동적인 데이터이므로 반드시 동적인 방식으로 받아와야 한다.

-TodoContorller.java(/todos서블릿)의 doGet메서드-

String action = request.getParameter("action");	 // 주소가 TODO/todos?=text일때 text의 값을 action에 저장
System.out.println(action);

switch(action) {
case "new":
	showNewForm(request, response);
	break;
case "insert":
	insertTodo(request, response);
	break;
case "delete":
	deleteTodo(request, response);
	break;
case "edit":
	showEditForm(request, response);
	break;
case "update":
	updateTodo(request, response);
	break;
case "list":	// localhost:8090/TODO/todos/list
	listTodo(request, response);
	break;
default:	// 요청 주소가 기본(/)이거나 잘못되었을 경우 로그인 페이지로 이동
	RequestDispatcher dispatcher = request.getRequestDispatcher("login/login.jsp");
	dispatcher.forward(request, response);
	break;
}// switch문 끝

-TodoContorller.java(/todos서블릿)의 listTodo메서드-

private void listTodo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	List<Todo> listTodo = todoDAO.selectAllTodos();	// DB에서 할일들을 가져와 리스트에 저장 
	request.setAttribute("listTodo", listTodo);		// 리스트를 리퀘스트에 저장
	
	RequestDispatcher dispatcher = request.getRequestDispatcher("todo/todo-list.jsp");
	dispatcher.forward(request, response);	// 위의 listTodo를 request에 저장한 상태로 todo-list.jsp페이지로 forward
}

로그인을 성공하면

이 페이지(todo-list.jsp)로 이동하게 된다.
아직은 할일리스트를 DB로부터 받아오지 않은 상태로, 상단의 Todo리스트 버튼(a태그)을 누르면

a태그 'Todo리스트'를 누르면 리스트를 가져와 listTodo리스트에 저장한 후 최종적으로 request에 저장되어 todo/todo-list.jsp페이지로 forward(데이터를 가진 채 이동)한다.

이 과정을 풀어서 서술하면

0) 로그인에 성공해 todo-list.jsp페이지로 이동한 후 상단의 Todo리스트 버튼(a태그)를 클릭. parameter의 action속성에 값 list를 가지고 /todos로 이동한다.
1) doGet메서드로 parameter의 action속성값을 받아와 변수action에 저장
2) listTodo메서드에서 todoDAO클래스를 구현한 TodoDaoImpl클래스로
3) TodoDaoImpl클래스의 selectALLTodos메서드 실행결과를 TodoController서블릿으로 가져와 결과를 리스트형태로 listTodo에 저장
4) 변수 listTodo를 attribute의 "listTodo"속성에 저장
5) request에 attribute의 값을 저장함
6) 위에서 만들어 둔 todo-list.jsp페이지에 <c:forEach var="todo" items="${listTodo}">로 listTodo속성의 값들을 가져와 변수 todo에 하나씩 저장해 그 하위태그에서 출력한다
(todo에는 리스트가 하나씩 차례로 저장된다고 생각하면 된다)
7) forEach문이 가져온 request에 더 이상 데이터가 없으면 반복문이 종료되며 태그를 닫는다


=> DB에서 값을 받아와 같은 페이지에 테이블만 추가된 상태로 새로고침된다고 보면 된다.


할일 추가/수정

할일의 추가/수정은 모두 todo-form.jsp페이지에 만들되 jstl의 if문을 통해 특정조건에 따라 코드를 따로 작성한다.
(jstl에는 else-if문이 없으므로 다중 if문으로 작성)

할일 추가

1) todo-list.jsp페이지의 a태그 '할일 추가'를 누르면 /todos?action=new 로 parameter가 넘어간다.
2) TodoContorller서블릿에 doGet메서드로 action속성에 new로 넘어가 showNewForm메서드가 실행된다.(doGet메서드는 바로위의 과정에 있으므로 코드생략)

=> showNewForm메서드에는 todo속성에 값을 저장하는 과정이 없으므로 todo속성은 null값인 채로 todo-form.jsp페이지로 이동하게 된다.
즉, '할일 추가' a태그의 parameter에 todo속성이 지정되어있지 않아 todo==null인게 아님!
(지정안되있는건 맞지만 수정기능에서 todo객체는 /todos서블릿의 showEditForm메서드에서 id값을 통해 DB에 쿼리문을 보낸 결과를 저장하여 값을 가지게 된다.)

-todo-form.jsp-

<div class="container">
<div class="row mt-5">
<div class="col-md-5 mx-auto">
<div class="card card-body">
<!-- 여기서부터 동적 페이지 -->
	<!-- 경우1. todo==null 이면 새로 입력, 경우2. todo!=null 이면 업데이트 -->
	<c:if test="${todo != null}">
		<form action="<%=request.getContextPath()%>/todos">
			<input type="hidden" name="action" value='update'>
	</c:if>
	<!-- 페이지를 처음 열었을 땐 todo에 값이 없으므로 경우2가 되어 할일추가기능을 수행 -->
	<c:if test="${todo == null}">
		<form action="<%=request.getContextPath()%>/todos">
			<input type="hidden" name="action" value='post'>
	</c:if>
	<h2>
		<c:if test="${todo != null}">할일 수정</c:if>
		<c:if test="${todo == null}">할일 추가</c:if>
	</h2>
	<c:if test="${todo != null}">
		<input type="hidden" class="form-control" name="id" value='<c:out value="${todo.id}"/>'>
	</c:if>
	<div class="form-group">
		<label>제목</label>
        	<input type="text" class="form-control" name="title" value='<c:out value="${todo.title}"/>' required>
	</div>
	<div class="form-group">
		<label>할일 설명</label>
        	<input type="text" class="form-control" name="description" value='<c:out value="${todo.description}"/>'>
		</div>
	<div class="form-group">
		<label>현재 상태</label>
            	<select class="form-control" name="isDone">
			<option value="false">진행중</option>
			<option value="true">완료</option>
		</select>
	</div>
	<div class="form-group">
		<label>목표 일자</label>
        	<input type="date" class="form-control" name="targetDate" value='<c:out value="${todo.targetDate}"/>'>
	</div>
	<div class="form-group mt-3">
		<button type="submit" class="btn btn-info">저장</button>
	</div>
	</form>
</div>
</div>
<!--.col-->
</div>
</div>


=> 할일 추가 버튼을 눌렀을 때 나타나는 화면.
todo속성이 null값이므로 그대로 칸이 비어있다.

할일 수정

  1. 수정페이지인 todo-form.jsp페이지에 수정을 클릭한 행의 할일정보를 띄운다.

    1) 액션의 수정/삭제 버튼 중 수정버튼(a태그)을 누르면 /todos페이지로 parameter에 action값(수정-edit, 삭제-delete)과 id값(forEach문으로 리스트의 한 행씩을 변수 todo에 넣었으므로 todo.id를 호출하면 현재 행의 id값을 받아올 수 있다.)을 가지고 이동한다.
    2) TodoContorller서블릿에 doGet메서드로 action속성에 edit로 넘어가 showEditForm메서드가 실행된다.(doGet메서드는 바로위의 과정에 있으므로 코드생략)
    3) 받아온 id속성의 값을 통해 todo showEditForm메서드에서 DB에서 id와 맞는 행의 다른 값도 가져온다.

-todo/todo-list.jsp-

<tbody>
  <!-- 동적 데이터(할일 데이터)를 테이블로 입력 -->
  <!-- 한 개의 할일을 변수todo에 저장 -->
  <c:forEach var="todo" items="${listTodo}">
    <tr>
      <td><c:out value="${todo.title}" /></td>
      <td><c:out value="${todo.targetDate}" /></td>
      <td><c:out value="${todo.status}" /></td>
      <td>
      	<a href="<%=request.getContextPath()%>/todos?action=edit&id=<c:out value='${todo.id}'/>" class="btn btn-outline-info btn-sm">수정</a>
      	<a href="<%=request.getContextPath()%>/todos?action=delete&id=<c:out value='${todo.id}'/>" class="btn btn-outline-danger btn-sm">삭제</a>
      </td>
    </tr>
  </c:forEach>
</tbody>

-TodoController.java(/todos서블릿)-

private void showEditForm(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	Long id = Long.parseLong(request.getParameter("id"));
	Todo theTodo = todoDAO.selectTodo(id);
	// 수정할 todo객체를 같이 보냄
	request.setAttribute("todo", theTodo);
	RequestDispatcher dispatcher = request.getRequestDispatcher("todo/todo-form.jsp");
	dispatcher.forward(request, response);	
}

=> 여기서 todo에 각 속성에 값을 가지고 todo-form.jsp페이지로 forward함.

다른부분은 todo-list.jsp페이지와 동일하므로 동적페이지 주석부분부터.(같은 부분은 생략)

-todo-form.jsp-

<!-- 여기서부터 동적 페이지 -->
<!-- 경우1. todo==null 이면 새로 입력, 경우2. todo!=null 이면 업데이트 -->
<c:if test="${todo != null}">
	<form action="<%=request.getContextPath()%>/todos">
		<input type="hidden" name="action"
			value='update'>
</c:if>
<!-- 페이지를 처음 열었을 땐 todo에 값이 없으므로  -->
<c:if test="${todo == null}">
	<form action="<%=request.getContextPath()%>/todos">
		<input type="hidden" name="action" value='post'>
</c:if>
<h2>
	<c:if test="${todo != null}">할일 수정</c:if>
	<c:if test="${todo == null}">할일 추가</c:if>
</h2>

<c:if test="${todo != null}">
	<input type="hidden" class="form-control" name="id"
		value='<c:out value="${todo.id}"/>'>
</c:if>

<div class="form-group mt-2">
	<label>제목</label> <input type="text" class="form-control"
		name="title" value='<c:out value="${todo.title}"/>' required>
</div>
<div class="form-group mt-2">
	<label>할일 설명</label> <input type="text" class="form-control"
		name="description" value='<c:out value="${todo.description}"/>'>
</div>
<div class="form-group mt-2">
	<label>현재 상태</label> <select class="form-control" name="isDone">
		<option value="false">진행중</option>
		<option value="true">완료</option>
	</select>
</div>
<div class="form-group mt-2">
	<label>목표 일자</label> <input type="date" class="form-control"
		name="targetDate" value='<c:out value="${todo.targetDate}"/>'>
</div>
<div class="form-group mt-3">
	<button type="submit" class="btn btn-outline-info">저장</button>
</div>
</form>

/todos서블릿에서 showEditForm메서드의 실행결과인 todo속성을 가지고 왔기때문에 두 개의 if문 중 todo!=null에 해당하게 된다.

페이지는 할일 추가와 같지만 가져온 정보로 빈 칸을 채워주느냐, 빈 칸으로 남겨두느냐의 차이이다.

!주의!
todo-form.jsp페이지에서 사용된 todo속성은 todo-list.jsp페이지에서 forEach문을 통해 넘어온 값이 아니다.
해당 행의 id값을 가지고 /todos서블릿의 showEditForm메서드에서 todoDAO.selectTodo메서드를 통해 DB에 쿼리문을 넘겨 받아온 결과(참고. 9일차 마지막의 CRUD중 test클래스의 검색 결과를 보면 된다)를 todo-form.jsp페이지에 띄워주는 것이다.


=> 할일 중 하나의 수정버튼을 눌렀을 때 나타나는 화면.
DB에서 받아온 값으로 빈칸을 채웠다.

  1. 불러온 값을 수정하여 저장버튼을 눌렀을 때 DB도 수정되도록

    1) 1번에서 불러온 todo-form페이지에서 할일을 수정한다.
    2) 1번의 todo-form.jsp페이지에서 저장 button을 누르면 form태그의 action주소로 input태그에 지정해둔 속성들이 doGet방식으로 이동한다.
    예- type="hidden"(안보이게) name="action"(속성이름은 action) value="update"(속성의 값은 update)
    => 여기서 id의 값은 h2태그 아래의 if문(todo!=null)아래의 input태그의 value에 들어가 있다. hidden속성으로 넘어가므로 눈에 보이지는 않는다.
    todo에 값이 없으면 todo.id역시 값이 없으므로 반드시 if문을 써야하는건 아니지만 구분이 편하도록 여기서는 넣어주었음.
    3) TodoController서블릿의 doGet메서드의 switch문에 의해 todoDAO의 updateTodo메서드가 호출되어 DB에 업데이트 쿼리문을 보내 DB의 할일정보를 업데이트한다.
    4) DB의 수정을 마지면 다시 todo-list.jsp페이지로 돌아와 변경된 DB에서 받아온 할일목록을 출력한다.


수정을 마친 화면.
수정한 할일이 DB에도 적용되어 정상적으로 수정을 마쳤다.

profile
천 리 길도 가나다라부터

0개의 댓글

관련 채용 정보