모도리는 공부중

21.03.08. SPRING - 정보 수정, FrontController 수정, 지금까지 수업 전체 코드 본문

K-디지털 빅데이터 분석서비스 개발자과정 20.11.02~21.04.12/JAVA

21.03.08. SPRING - 정보 수정, FrontController 수정, 지금까지 수업 전체 코드

공부하는 모도리 2021. 3. 8. 18:32
728x90
반응형

아이디에 a tag를 걸어서 아이디를 누르면 상세보기로 연결되도록 만들어봅시다.

WebContent - WEB-INF - memberList.jsp

	<c:forEach var="vo" items="${list }">
		<tr>
			<td>${vo.num}</td>
			<td><a href="/mvc/memberContent.do?num=${vo.num }">${vo.id}</a></td>
			<td>${vo.pass}</td>
			<td>${vo.name}</td>
			<td>${vo.age}</td>
			<td>${vo.phone}</td>
			<td>${vo.email}</td>
			<td><input type="button" value="삭제" class="btn btn-default" onclick="memberDel(${vo.num})"></td>
		</tr>
	</c:forEach>

get방식으로 넘겨지게 설정한다. 그리고 이 작업을 수행할 프론트 컨트롤러에 코드를 추가한다.

 else if (command.equals("/memberContent.do")) {
			// memberDelete를 대신 처리할 POJO 생성
			controller = new MemberContentController();
			nextView = controller.requestHandler(request, response);
			RequestDispatcher rd = request.getRequestDispatcher(nextView);
			rd.forward(request, response);
		}

위 코드를 추가하고 나면 MemberContentController에 빨간줄이 뜬다. 이것과 연결되는 POJO를 kr.smhrd.controller패키지에 MemberContentController라는 이름의 class를 생성한다. 이후 implements Controller를 작성하여 오버라이드해준다.

package kr.smhrd.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.model.MemberDAO;
import kr.smhrd.model.MemberDAOImpl;
import kr.smhrd.model.MemberVO;

public class MemberContentController implements Controller{

	@Override
	public String requestHandler(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		int num = Integer.parseInt(request.getParameter("num"));
		
		MemberDAO dao = new MemberDAOImpl();
		MemberVO vo = dao.memberContent(num);
		request.setAttribute("vo", vo);
		
		return "/WEB-INF/view/memberContent.jsp";
	}

}

이제 memberContent를 구현하러 갑시다.

 

MemberDAOImpl

	@Override
	public MemberVO memberContent(int num) {

		SqlSession session = sqlSessionFactory.openSession();
		MemberVO vo = session.selectOne("memberContent", num);
		session.close();
		
		return vo;
	}

"memberContent"와 연결지어 활동할 mapper에 sql을 작성하러 갑시다.

	<select id="memberContent" resultType="kr.smhrd.model.MemberVO" parameterType="Integer">
		select * from memtbl where num = #{num}
	</select>

이제 JDBC는 없습니다. myBatis를 이용하면 이렇게 MVC가 간단하게 끝납니다.

그리고 나면 다시 MemberContentController로 돌아와서 return을 바꿔주어야 한다. 하지만 지금은 아직 거기까지 진도를 나가지 않고 아까 만들어둔 상태 그대로 둘 것이다. 나중에 바꿀 것이니 기억!

		return "/WEB-INF/view/memberContent.jsp"; // pre-fix인 /WEB-INF/view와 post-fix인 jsp.
		// 지금은 이렇게 두지만 나중에 유지보수를 위해 바꿔주어야 합니다.

이제 jsp를 만들어준다. 이 jsp는 멤버 상세보기를 담당한다. 빠른 테이블 작성을 위해 전에 받은 테이블 만들어주는 사이트를 이용해도 좋다. 만들고 나서 사용하지 않는 class속성을 일일히 지워주는 것이 더 귀찮다면 자바의 복붙을 도와주는 몇가지 기능을 이용하여 직접 만드는 것도 좋다.

 

memberContent.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
	pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Insert title here</title>
</head>
<body>
	<table class="table table-borderd" width: 628px">
		<colgroup>
			<col style="width: 105px">
			<col style="width: 523px">
		</colgroup>
		<thead>
			<tr>
				<th>번호</th>
				<th>${vo.num }</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td>아이디</td>
				<td>${vo.id }</td>
			</tr>
			<tr>
				<td>비밀번호</td>
				<td>${vo.pass }</td>
			</tr>
			<tr>
				<td>이름</td>
				<td>${vo.name }</td>
			</tr>
			<tr>
				<td>나이</td>
				<td>${vo.age }</td>
			</tr>
			<tr>
				<td>전화번호</td>
				<td>${vo.phone }</td>
			</tr>
			<tr>
				<td>이메일</td>
				<td>${vo.email }</td>
			</tr>
			<tr>
				<td colspan="2">수정하기 취소 리스트</td>
			</tr>
		</tbody>
	</table>
</body>
</html>

memberList.do 페이지를 실행하면 아이디가 파랗게 클릭할 수 있도록 변한 것을 확인할 수 있다. 클릭하면 다음 사진처럼 상세보기 페이지로 이동도 잘 된다.

이제 나이, 전화번호, 이메일을 수정할 수 있도록 코드를 수정한다.

<%@ page language="java" contentType="text/html; charset=EUC-KR"
	pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Insert title here</title>
</head>
<body>
<form action="/mvc/memberUpdate.do" method="post">
<input type="hidden" name="num" value="${vo.num }">
	<table class="table table-borderd" width: 628px">
		<colgroup>
			<col style="width: 105px">
			<col style="width: 523px">
		</colgroup>
		<thead>
			<tr>
				<th>번호</th>
				<th>${vo.num }</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td>아이디</td>
				<td>${vo.id }</td>
			</tr>
			<tr>
				<td>비밀번호</td>
				<td>${vo.pass }</td>
			</tr>
			<tr>
				<td>이름</td>
				<td>${vo.name }</td>
			</tr>
			<tr>
				<td>나이</td>
				<td><input type="text" name="age" value="${vo.age }"></td>
			</tr>
			<tr>
				<td>전화번호</td>
				<td><input type="text" name="phone" value="${vo.phone }"></td>
			</tr>
			<tr>
				<td>이메일</td>
				<td><input type="text" name="email" value="${vo.email }"></td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<input type="submit" value="수정하기 ">
					<input type="reset" value="취소">
					<input type="button" value="리스트">
				</td>
			</tr>
		</tbody>
	</table>
</form>
</body>
</html>

화면 특성상 오른쪽에 치우쳐져 보일 뿐, 실상 align="center"는 잘 먹힌 상태이다.

값을 수정할 때 나이, 전화번호, 이메일 파라미터와 수정할 대상자가 누구인지를 알 수 있도록 번호 파라미터를 같이 넘겨주어야 한다. 이걸 한 번에 엮어서 보내는 방법은 form태그 방식을 택한다. table태그를 form태그로 감싸고 action과 method를 지정해준 후 프론트 컨트롤러에 해당 리모트를 설정한다.

		} else if (command.equals("/memberUpdate.do")) {
			// POJO 생성
			controller = new MemberUpdateController();
			nextView = controller.requestHandler(request, response);
			response.sendRedirect(nextView);
		}

 

kr.smhrd.controller패키지에 memberUpdateController 클래스 생성

package kr.smhrd.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.model.MemberDAO;
import kr.smhrd.model.MemberDAOImpl;
import kr.smhrd.model.MemberVO;

public class memberUpdateController implements Controller{

	@Override
	public String requestHandler(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 파라미터 수집(VO)
		int num = Integer.parseInt(request.getParameter("num"));
		int age = Integer.parseInt(request.getParameter("age"));
		String phone = request.getParameter("phone");
		String email = request.getParameter("email");
		
		MemberVO vo = new MemberVO();
		vo.setNum(num);
		vo.setAge(age);
		vo.setPhone(phone);
		vo.setEmail(email);
		
		// Model 연동
		MemberDAO dao = new MemberDAOImpl();
		int cnt = dao.memberUpdate(vo);
		String nextPage = null;
		if (cnt > 0) {
			// 수정 성공 → 리스트 페이지로 요청(memberList.do)
			nextPage = "/mvc/memberList.do";
		} else {
			throw new ServletException("not update"); // 예외를 생성하여 WAS가 예외처리하도록 던진다.
		}
		
		return nextPage;
	}
}

insert와 많은 부분이 비슷하므로 그대로 가져다가 일부만 수정하여 사용한다.

 

memberDAOImpl

	@Override
	public int memberUpdate(MemberVO vo) {

		SqlSession session = sqlSessionFactory.openSession();
		int cnt = session.update("memberUpdate", vo);
		session.commit();
		session.close();
		
		return cnt;
	}

 

memberMapper.xml

	<update id="memberUpdate" parameterType="kr.smhrd.model.MemberVO">
		update memtbl set age=#{age}, phone=#{phone}, email=#{email}
		where num = #{num}
	</update>

 

전부 다 끝나면 프론트컨트롤러는 이 상태가 된다.

package kr.smhrd.frontcontroller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.controller.Controller;
import kr.smhrd.controller.MemberContentController;
import kr.smhrd.controller.MemberDeleteController;
import kr.smhrd.controller.MemberInsertController;
import kr.smhrd.controller.MemberListController;
import kr.smhrd.controller.MemberRegisterController;
import kr.smhrd.controller.memberUpdateController;

@WebServlet("*.do")
public class MemberFrontController extends HttpServlet {
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// POST방식으로 넘어오는 경우에는 한글값을 인코딩해줄 필요가 있다.
		request.setCharacterEncoding("euc-kr");
		// GET방식은 한글로 넘어오는 경우가 거의 없으므로 인코딩 필요가 X.
		
		// 1. 클라이언트의 요청정보를 확인하기
		String reqUrl = request.getRequestURI(); // 클라이언트가 요청한 url정보를 얻어와서 reqUrl변수에 담아준다. 
//		System.out.println(reqUrl);
		
		// Context Path = ?
		String ctx = request.getContextPath();
//		System.out.println(ctx); // Context Path인 /mvc만 잘라내기
		
		String command = reqUrl.substring(ctx.length()); // /memberList.do만 잘라오려면 어떻게 해야할까?
		System.out.println(command);
		
		// 2. 해당 요청에 따른 분기 작업(HandlerMapping) : if ~ else ~
		Controller controller;
		String nextView = null;
		if (command.equals("/memberList.do")) {
//			MemberListController controller = new MemberListController(); ← 이것의 부모타입인 Controller를 상단에 미리 선언
			controller = new MemberListController();
			nextView = controller.requestHandler(request, response);
			// forward(RequestDispatcher)
			RequestDispatcher rd = request.getRequestDispatcher(nextView);
			rd.forward(request, response);
		} else if (command.equals("/memberInsert.do")) {
//			MemberInsertController controller = new MemberInsertController();
			controller = new MemberInsertController(); // 일할 알바생 controller 호출
			nextView = controller.requestHandler(request, response); // controller를 일하게 시키고 일이 끝나면 nextView로 값을 넘긴다.
			response.sendRedirect(nextView);
		} else if (command.equals("/memberRegister.do")) {
			// memberRegister.html로 가라고 경로만 알려주면 된다. 다른 업무처리는 없음.
			controller = new MemberRegisterController();
			nextView = controller.requestHandler(request, response);
			RequestDispatcher rd = request.getRequestDispatcher(nextView);
			rd.forward(request, response);
		} else if (command.equals("/memberDelete.do")) {
			// memberDelete를 대신 처리할 POJO 생성
			controller = new MemberDeleteController();
			nextView = controller.requestHandler(request, response);
			response.sendRedirect(nextView);
		} else if (command.equals("/memberContent.do")) {
			// POJO 생성
			controller = new MemberContentController();
			nextView = controller.requestHandler(request, response);
			RequestDispatcher rd = request.getRequestDispatcher(nextView);
			rd.forward(request, response);
		} else if (command.equals("/memberUpdate.do")) {
			// POJO 생성
			controller = new memberUpdateController();
			nextView = controller.requestHandler(request, response);
			response.sendRedirect(nextView);
		}
	}

}

위의 코드를 보면 중복되는 몇가지 코드가 있음을 알 수 있다. 그 중에 forward를 담당하는 코드를 전부 지워준다. 하단에서 if문으로 일괄처리해줄 예정이니 미련없이 지우자.

 

DeleteController, InsertController, UpdateController는 /mvc앞에 redirect:를 추가하고, ContentController, ListController, RegisterController는 WEB-INF/view/와 .jsp 혹은 .html 삭제해준다.

그리고 DeleteController, InsertController, UpdateController에 다음의 ctx 코드 한 줄을 추가하고 nextPage 코드는 수정해준다.

String ctx = request.getContextPath(); // /mvc

nextPage = "redirect:"+ctx+"/memberList.do";

 

MVC 마무리는 내일 한 시간 동안 더 진행하고 내일부터는 새로운 파트를 나가보도록 하겠습니다.

 

지금까지 수업한 파일들 코드 정리는 더보기란에 풀어놓으면서 오늘의 노트 정리를 마무리해본다!!!

 

Java Resources - src 에 생성하는 package 모음

kr.smhrd.controller

더보기

클래스 파일의 경우 파일명을 바꾸면 바로 오류가 생긴다. 파일명을 바꾸고 싶다면 그 안에 있는 코드를 복사한 후 파일을 지우고 새로운 파일명으로 만들어서 새 파일에 붙여넣어주도록 하자.

CalcController.java 클래스

package kr.smhrd.controller;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.model.MemberVO;

@WebServlet("/calc.do")
public class CalcController extends HttpServlet {
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		ArrayList<MemberVO> list = new ArrayList<MemberVO>();
		MemberVO vo = new MemberVO();
		vo.setId("modory");
		vo.setPass("123456");
		vo.setName("모도리");
		vo.setAge(30);
		vo.setPhone("010-2222-3333");
		vo.setEmail("modory@modory.com");
		
		list.add(vo);
		
		MemberVO vo1 = new MemberVO();
		vo1.setId("sim");
	    vo1.setPass("123");
	    vo1.setName("sim");
	    vo1.setAge(30);
	    vo1.setPhone("010-7777-7777");
	    vo1.setEmail("sim@sim.com");
		
		list.add(vo1);
	    
		request.setAttribute("list", list); // int(Integer, String) - Object
		// 이 상태는 sum이 int타입인데 오류가 발생하지 않고 있다. 왜? java의 boxing이 이루어졌기 때문.
		// boxing : int -> Integer
		// java가 최신버전이다보니 int를 Integer로 자동 바꿔주는 기능 덕분에 에러가 나지 않고 있다.
		
		// 결과를 test.jsp에서 출력(forward)*****
		RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/view/test.jsp");
		rd.forward(request, response);
	}

}

Controller.java 클래스

package kr.smhrd.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface Controller {
	// void -> String
	public String requestHandler(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException;
	
}

MemberContentController.java 클래스

package kr.smhrd.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.model.MemberDAO;
import kr.smhrd.model.MemberDAOImpl;
import kr.smhrd.model.MemberVO;

public class MemberContentController implements Controller{

	@Override
	public String requestHandler(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		int num = Integer.parseInt(request.getParameter("num"));
		
		MemberDAO dao = new MemberDAOImpl();
		MemberVO vo = dao.memberContent(num);
		request.setAttribute("vo", vo);
		
		return "memberContent"; // pre-fix인 /WEB-INF/view와 post-fix인 jsp.
		// 지금은 이렇게 두지만 나중에 유지보수를 위해 바꿔주어야 합니다.
	}

}

MemberDeleteController.java 클래스

package kr.smhrd.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.model.MemberDAO;
import kr.smhrd.model.MemberDAOImpl;

public class MemberDeleteController implements Controller{

	@Override
	public String requestHandler(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String ctx = request.getContextPath(); // /mvc
		
		int num = Integer.parseInt(request.getParameter("num"));
		
		MemberDAO dao = new MemberDAOImpl();
		int cnt = dao.memberDelete(num); // method를 구현해줍시다. → MemberDAOImpl.java
		String nextPage = null;
		if (cnt > 0) { // 성공하면 다시 리스트 페이지로 이동
			nextPage = "redirect:"+ctx+"/memberList.do";
		} else {
			throw new ServletException("not delete");
		}
		return nextPage;
	}

}

MemberInsertController.java 클래스

package kr.smhrd.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.model.MemberDAO;
import kr.smhrd.model.MemberDAOImpl;
import kr.smhrd.model.MemberVO;

public class MemberInsertController implements Controller{

	@Override
	public String requestHandler(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String ctx = request.getContextPath(); // /mvc
		
		// 파라미터 수집(VO - value object)

		/*	지금까지 우리는 getParameter를 이용하여 각각의 name을 직접 하나씩 받아서 진행했다.
			하지만 앞으로 배울 spring framework를 이용하면 파라미터수집을 대신해준다. 파라미터 이름과 vo에 있는 value 이름이 같으면 자동으로 들어간다.
			이런 이유로 프레임워크는 유지보수 측면에서 상당히 유용하고 편리하다. 일단은 배운대로 파라미터를 직접 입력한다.	*/
		
//		frontcontroller가 할 일을 대신 해야하므로 request와 response를 받아야한다.
		String id = request.getParameter("id");
		String pass = request.getParameter("pass");
		String name = request.getParameter("name");
		int age = Integer.parseInt(request.getParameter("age"));
		String phone = request.getParameter("phone");
		String email = request.getParameter("email");
		
		MemberVO vo = new MemberVO();
		vo.setId(id);
		vo.setPass(pass);
		vo.setName(name);
		vo.setAge(age);
		vo.setPhone(phone);
		vo.setEmail(email);
		
		// Model 연동
		MemberDAO dao = new MemberDAOImpl();
		int cnt = dao.memberInsert(vo);
		String nextPage = null;
		if (cnt > 0) {
			// 가입 성공 → 리스트 페이지로 요청(memberList.do)
			nextPage = "redirect:"+ctx+"/memberList.do";
			// jsp로 바로 갈 수 없으며 list page에서 또 요청해야 jsp로 갈 수 있다.
		} else {
			throw new ServletException("not insert"); // 예외를 생성하여 WAS가 예외처리하도록 던진다.
		}
		
		return nextPage;
	}

}

MemberListController.java 클래스

package kr.smhrd.controller;

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

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.model.MemberDAO;
import kr.smhrd.model.MemberDAOImpl;
import kr.smhrd.model.MemberVO;
// 유연성이 떨어진다?
public class MemberListController implements Controller {

	@Override
	public String requestHandler(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		MemberDAO dao = new MemberDAOImpl();
		List<MemberVO> list = dao.memberList();
		// ★ 객체 바인딩
		request.setAttribute("list", list);
		// 컨트롤러님 forward할 다음 페이지는 memberList.jsp입니다.
		return "memberList";
	}

}

MemberRegisterController.java 클래스

package kr.smhrd.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MemberRegisterController implements Controller{

   @Override
   public String requestHandler(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {

      return "memberRegister"; // 회원가입 페이지
   }

}

MemberUpdateController.java 클래스

package kr.smhrd.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.model.MemberDAO;
import kr.smhrd.model.MemberDAOImpl;
import kr.smhrd.model.MemberVO;

public class MemberUpdateController implements Controller{

	@Override
	public String requestHandler(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String ctx = request.getContextPath(); // /mvc
		
		// 파라미터 수집(VO)
		int num = Integer.parseInt(request.getParameter("num"));
		int age = Integer.parseInt(request.getParameter("age"));
		String phone = request.getParameter("phone");
		String email = request.getParameter("email");
		
		MemberVO vo = new MemberVO();
		vo.setNum(num);
		vo.setAge(age);
		vo.setPhone(phone);
		vo.setEmail(email);
		
		// Model 연동
		MemberDAO dao = new MemberDAOImpl();
		int cnt = dao.memberUpdate(vo);
		String nextPage = null;
		if (cnt > 0) {
			// 수정 성공 → 리스트 페이지로 요청(memberList.do)
			nextPage = "redirect:"+ctx+"/memberList.do";
		} else {
			throw new ServletException("not update"); // 예외를 생성하여 WAS가 예외처리하도록 던진다.
		}
		
		return nextPage;
	}
}

kr.smhrd.db

더보기

member.sql

create table memtbl(
	num number not null,
	id varchar2(20) not null primary key,
	pass varchar2(20) not null,
	name varchar2(20) not null,
	age number not null,
	phone varchar2(20) not null,
	email varchar2(20) not null
);

create sequence memtbl_num_seq;

-- 관리자
insert into MEMTBL values(memtbl_num_seq.nextval, 'admin', 'bit', '관리자', 32, '010-1111-1111', 'admin@smhrd.com');

select * from MEMTBL;

설정값 ↓

Type : Oracle 11

Name : New Oracle

Database : xe

kr.smhrd.frontcontroller

더보기

MemberFrontController.java 클래스

package kr.smhrd.frontcontroller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.smhrd.controller.Controller;
import kr.smhrd.controller.MemberContentController;
import kr.smhrd.controller.MemberDeleteController;
import kr.smhrd.controller.MemberInsertController;
import kr.smhrd.controller.MemberListController;
import kr.smhrd.controller.MemberRegisterController;
import kr.smhrd.controller.MemberUpdateController;

@WebServlet("*.do")
public class MemberFrontController extends HttpServlet {
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// POST방식으로 넘어오는 경우에는 한글값을 인코딩해줄 필요가 있다.
		request.setCharacterEncoding("euc-kr");
		// GET방식은 한글로 넘어오는 경우가 거의 없으므로 인코딩 필요가 X.
		
		// 1. 클라이언트의 요청정보를 확인하기
		String reqUrl = request.getRequestURI(); // 클라이언트가 요청한 url정보를 얻어와서 reqUrl변수에 담아준다. 
//		System.out.println(reqUrl);
		
		// Context Path = ?
		String ctx = request.getContextPath();
//		System.out.println(ctx); // Context Path인 /mvc만 잘라내기
		
		String command = reqUrl.substring(ctx.length()); // /memberList.do만 잘라오려면 어떻게 해야할까?
		System.out.println(command);
		
		// 2. 해당 요청에 따른 분기 작업(HandlerMapping) : if ~ else ~
		Controller controller;
		String nextView = null;
		if (command.equals("/memberList.do")) {
//			MemberListController controller = new MemberListController(); ← 이것의 부모타입인 Controller를 상단에 미리 선언
			controller = new MemberListController();
			nextView = controller.requestHandler(request, response);
		} else if (command.equals("/memberInsert.do")) {
//			MemberInsertController controller = new MemberInsertController();
			controller = new MemberInsertController(); // 일할 알바생 controller 호출
			nextView = controller.requestHandler(request, response); // controller를 일하게 시키고 일이 끝나면 nextView로 값을 넘긴다.
		} else if (command.equals("/memberRegister.do")) {
			// memberRegister.html로 가라고 경로만 알려주면 된다. 다른 업무처리는 없음.
			controller = new MemberRegisterController();
			nextView = controller.requestHandler(request, response);
		} else if (command.equals("/memberDelete.do")) {
			// memberDelete를 대신 처리할 POJO 생성
			controller = new MemberDeleteController();
			nextView = controller.requestHandler(request, response);
		} else if (command.equals("/memberContent.do")) {
			// POJO 생성
			controller = new MemberContentController();
			nextView = controller.requestHandler(request, response);
		} else if (command.equals("/memberUpdate.do")) {
			// POJO 생성
			controller = new MemberUpdateController();
			nextView = controller.requestHandler(request, response);
		}
		
		// ---------------------------------------------------
		// nextPage = "redirect:/mcv/memberList.do"
		// nextPage = "/WEB-INF/view/memberList.jsp"
		if (nextView != null) {
			if (nextView.indexOf("redirect:")!=-1) { // -1이 아니면 값이 있다는 뜻
				// redirect
				response.sendRedirect(nextView.split(":")[1]); // split해서 :기준으로 앞이 0, 뒤가 1. /mvc/memberList.do
			} else {
				// forward
				RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/view/"+nextView+".jsp");
				rd.forward(request, response);
			}
		}
	}

}

kr.smhrd.model

더보기

MemberDAO.java 인터페이스

package kr.smhrd.model;

import java.util.List;

public interface MemberDAO {
	// CRUD
	public int memberInsert(MemberVO vo);
	public List<MemberVO> memberList(); // list니까 vo타입으로 받아줘야겠죠?
	public int memberUpdate(MemberVO vo); // 0이면 실패, 1이면 성공. true false를 받기 위한 변수
	public int memberDelete(int num); // 키값은 num에 해당하는 db값을 삭제해주면 되겠죠?
	public MemberVO memberContent(int num); // 선택한(특정 키값(고유값)) 회원 상세보기
	// 위의 다섯가지 로직은 ERP시스템에서 거의 공통으로 사용된다.
}

MemberDAOImpl.java 클래스

package kr.smhrd.model;

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

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
// JDBC -> myBatis Framework
public class MemberDAOImpl implements MemberDAO {
	
//					***************
	private static SqlSessionFactory sqlSessionFactory;

	static { // static블럭(초기화블럭) 생성
	// └ (객체가 생성될때 딱 한번 실행된다) DB작업은 실행될 때 딱 한번만 연결되면 되기 때문
		try {
			// xml파일을 읽어서 sqlsessionFactory 를 만드는거다.
			String resource = "kr/smhrd/myBatis/config.xml";
			InputStream inputStream;

			inputStream = Resources.getResourceAsStream(resource);
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	@Override
	public int memberInsert(MemberVO vo) {
		
		SqlSession session = sqlSessionFactory.openSession();
		int cnt = session.insert("memberInsert", vo); // ("sql명령문에 들어갈 것", 받아온 vo)  
		session.commit(); // 완료
		session.close(); // 반납
		return cnt;
	}

	@Override
	public List<MemberVO> memberList() {
		
		SqlSession session = sqlSessionFactory.openSession();
		
//		String SQL = "select * from membl"; ← 이제 이 쿼리는 여기에 쓸 수 없다. MemberMapper.xml에서 작성.
//		그럼 mapper에 있는 sql을 어떻게 연결할 것인가? mapper에서 sql문을 select태그로 감싸주면 된다.
//		select로 감쌌으니 id를 부여할 수 있다. 그 id를 이용해서 연결하는데, id값은 보통 method이름을 그대로 부여하는게 일반적이다.
		
		// selectList : db에서 여러개의 데이터를 가지고 오는 작업
		List<MemberVO> list = session.selectList("memberList"); // mapper에서 MemberVO로 넘겨주었으니 vo list로 값을 받는다.
		session.close(); // session 반납
		return list;
	}

	@Override
	public int memberUpdate(MemberVO vo) {

		SqlSession session = sqlSessionFactory.openSession();
		int cnt = session.update("memberUpdate", vo);
		session.commit();
		session.close();
		
		return cnt;
	}

	@Override
	public int memberDelete(int num) {

		SqlSession session = sqlSessionFactory.openSession();
		int cnt = session.delete("memberDelete", num);	// delete sql 만들러 떠납시다. → MemberMapper.xml
		session.commit();
		session.close();
		
		return cnt;
	}

	@Override
	public MemberVO memberContent(int num) {

		SqlSession session = sqlSessionFactory.openSession();
		MemberVO vo = session.selectOne("memberContent", num);
		session.close();
		
		return vo;
	}

}

MemberVO.java 클래스

package kr.smhrd.model;

public class MemberVO {
	private int num;
	private String id;
	private String pass;
	private String name;
	private int age;
	private String phone;
	private String email;
	
	public MemberVO() { } // defalut 생성자는 사용을 하든 안하든 반드시 만들어준다.
	
	public int getNum() {
		return num;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPass() {
		return pass;
	}
	public void setPass(String pass) {
		this.pass = pass;
	}
	public String getName() {
		return name;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	
	
}

kr.smhrd.myBatis

더보기

xml은 xml file, properties는 properties file을 찾아서 만들어주는게 좋다. 각각 서로 다르다.

config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <properties resource="kr/smhrd/myBatis/db.properties"/>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="kr/smhrd/myBatis/MemberMapper.xml"/>
  </mappers>
</configuration>

db.properties (아래 코드는 띄어쓰기도 용납 못한다. 수정 없이 그대로 복붙해서 사용할 것)

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:XE
username=hr
password=hr

MemberMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.smhrd.mybatis.MemberMapper"> <!-- namespace로 mapper가 중복되지 않도록 구분 -->

	<!-- sql문을 select태그로 감싸서 id값을 주면 MemberDAOImpl에 있는 memberList메소드와 연결할 수 있다. -->
	<!-- resultType은 select태그 안에 있는 결과값을 어떻게 표시할 것인지 나타낸다. -->
	<!-- resultType을 MemberVO타입으로 묶어주는데 이것은 패키지 안에 있으므로 경로를 전부 작성해주어야 한다. -->
	<select id="memberList" resultType="kr.smhrd.model.MemberVO">
		select * from memtbl
	</select>
	
	<insert id="memberInsert" parameterType="kr.smhrd.model.MemberVO">
		insert into memtbl values(memtbl_num_seq.nextval,
		#{id},
		#{pass},
		#{name},
		#{age},
		#{phone},
		#{email}
		 )
	</insert>
	
	<delete id="memberDelete" parameterType="Integer">
		delete from memtbl where num = #{num}
	</delete> <!-- delete sql 작성이 끝났으면 다시 FrontController로 -->
	
	<select id="memberContent" resultType="kr.smhrd.model.MemberVO" parameterType="Integer">
		select * from memtbl where num = #{num}
	</select>
	
	<update id="memberUpdate"  parameterType="kr.smhrd.model.MemberVO">
		update memtbl set age=#{age}, phone=#{phone}, email=#{email}
		where num = #{num}
	</update>
</mapper>

 

Web Content - WEB-INF - view

더보기

memberContent.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
	pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Insert title here</title>
</head>
<body>
<form action="/mvc/memberUpdate.do" method="post">
<input type="hidden" name="num" value="${vo.num }">
	<table class="table table-borderd" width: 628px">
		<colgroup>
			<col style="width: 105px">
			<col style="width: 523px">
		</colgroup>
		<thead>
			<tr>
				<th>번호</th>
				<th>${vo.num }</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td>아이디</td>
				<td>${vo.id }</td>
			</tr>
			<tr>
				<td>비밀번호</td>
				<td>${vo.pass }</td>
			</tr>
			<tr>
				<td>이름</td>
				<td>${vo.name }</td>
			</tr>
			<tr>
				<td>나이</td>
				<td><input type="text" name="age" value="${vo.age }"></td>
			</tr>
			<tr>
				<td>전화번호</td>
				<td><input type="text" name="phone" value="${vo.phone }"></td>
			</tr>
			<tr>
				<td>이메일</td>
				<td><input type="text" name="email" value="${vo.email }"></td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<input type="submit" value="수정하기 " class="btn btn-default">
					<input type="reset" value="취소" class="btn btn-default">
					<input type="button" value="리스트" class="btn btn-success" onclick="location.href='/mvc/memberList.do'">
				</td>
			</tr>
		</tbody>
	</table>
</form>
</body>
</html>

memberList.jsp

<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
  <script type="text/javascript">
  	function memberIn(){
  		location.href="/mvc/memberRegister.do";
  	}
  	function memberDel(num){
  		location.href="/mvc/memberDelete.do?num="+num; // 쿼리스트링 방식을 이용하여 num값이 주소에 get방식으로 붙어 넘어가도록 지정한다.
  	}
  </script>
</head>
<body>
<table class="table">
	<tr>
		<td>번호</td>
		<td>아이디</td>
		<td>비밀번호</td>
		<td>이름</td>
		<td>나이</td>
		<td>전화번호</td>
		<td>이메일</td>
		<td>삭제</td>
	</tr>
	<c:forEach var="vo" items="${list }">
		<tr>
			<td>${vo.num}</td>
			<td><a href="/mvc/memberContent.do?num=${vo.num }">${vo.id}</a></td>
			<td>${vo.pass}</td>
			<td>${vo.name}</td>
			<td>${vo.age}</td>
			<td>${vo.phone}</td>
			<td>${vo.email}</td>
			<td><input type="button" value="삭제" class="btn btn-default" onclick="memberDel(${vo.num})"></td>
		</tr>
	</c:forEach>
	<tr>
		<td colspan="8" align="right">
			<input type="button" value="회원가입" class="btn btn-primary" onclick="memberIn()">
		</td>
	</tr>
</table>
</body>
</html>

memberRegister.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
	href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script
	src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Insert title here</title>
</head>
<body>
	<form action="/mvc/memberInsert.do" method="post">
	<!-- /mvc 앞에는 항상 127.0.0.1:8081이 붙어있다는 전제가 있다. -->
	<!-- 많은 양의 데이터를 보낼 때는 post방식을 취한다. --> 
		<table class="table">
			<thead>
				<tr>
					<th class="tg-0pky">아이디</th>
					<th class="tg-0pky"><input type="text" name="id"></th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td class="tg-0pky">비밀번호</td>
					<td class="tg-0pky"><input type="password" name="pass"></td>
				</tr>
				<tr>
					<td class="tg-0pky">이름</td>
					<td class="tg-0pky"><input type="text" name="name"></td>
				</tr>
				<tr>
					<td class="tg-0pky">나이</td>
					<td class="tg-0pky"><input type="text" name="age"></td>
				</tr>
				<tr>
					<td class="tg-0pky">전화번호</td>
					<td class="tg-0pky"><input type="text" name="phone"></td>
				</tr>
				<tr>
					<td class="tg-0pky">이메일</td>
					<td class="tg-0pky"><input type="text" name="email"></td>
				</tr>
				<tr>
					<td class="tg-0pky" colspan="2" align="center">
						<input type="submit" value="가입" class="btn btn-primary" />
						<input type="reset" value="취소" class="btn btn-primary" />
					</td>
				</tr>
			</tbody>
		</table>
	</form>
</body>
</html>

 

추가 ) Web Content - WEB-INF 에 있는 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>MVC</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

728x90
반응형
Comments