본문 바로가기
ETC

Model2: MVC 실습

by EUN-JI 2023. 11. 16.
-- EX10 MVC 실습 워크시트

--회원정보 테이블
CREATE TABLE TP01_MEMBER (
    USER_ID VARCHAR2(10) PRIMARY KEY,
    USER_PW VARCHAR2(10) NOT NULL,
    USER_NAME VARCHAR2(50) NOT NULL,
    USER_EMAIL VARCHAR2(50),
    REG_DATE DATE DEFAULT SYSDATE
);

COMMIT;

<oracle DBMS>ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My Web</title>
</head>
<body>

	<h1 style="text-align: center; margin-top: 3em;">MY WEB INDEX PAGE</h1>
	
	<div style="text-align: center;">
		<a href="member/loginForm.jsp">로그인하기</a>
	</div>
	
	
</body>
</html>

<index.jsp>ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인</title>

<!--css적용하기  -->
<link type="text/css" rel="stylesheet" href="css/loginForm.css">
</head>
<body>

	<h1 class="title">로그인</h1>
	<h4 class="message">로그인을 해야 게시판을 사용할 수 있습니다.</h4>
	
	<form action="../login" method="post" enctype="application/x-www-form-urlencoded">
		<div class="input">
			<input type="text" placeholder="아이디" name="user_id">
		</div>
		<div class="input">
			<input type="password" placeholder="비밀번호" name="user_pw">
		</div>
		
		<div class="input">
			<input type="submit" value="로그인">
		</div>
	</form>
	
	<hr>
	
	<div class="input">
		<a href="signupForm.jsp">회원가입</a>
	</div>
	
	
</body>
</html>

<loginForm.jsp>ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입</title>

<!--css적용하기  -->
<link type="text/css" rel="stylesheet" href="css/loginForm.css">
</head>
<body>
	
	<h1 class="title">회원가입</h1>
	<h4 class="message">이미 회원이신가요? &nbsp;&nbsp;<a href="loginForm.jsp">로그인화면으로 돌아가기</a> </h4>
	
	<hr>
	
	<form action="../signup"method="post" enctype="application/x-www-form-urlencoded">
	<div class="input">
			<input type="text" placeholder="아이디" name="user_id">
		</div>
		<div class="input">
			<input type="password" placeholder="비밀번호" name="user_pw">
		</div>
		<div class="input">
			<input type="text" placeholder="이름" name="user_name">
		</div>
		<div class="input">
			<input type="email" placeholder="이메일" name="user_email">
		</div>
		
		<div class="input">
			<input type="submit" value="가입하기">
			<input type="reset" value="다시입력">
		</div>
	</form>
	
</body>
</html>

<signupForm.jsp>ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

@charset "UTF-8";

@font-face{
	font-family: 'jn';
	src: url("../../font/jn.ttf");
}

/*텍스트관련 스타일은 자식요소들에서 적용됨. 그래서 문서의 공통적인 적용을 하려면..*/
body{font-family: 'jn','Times New Roman', Times, serif; padding: 3em;}

.title{text-align: center;}
.message{text-align: center; line-height: 3em;}

.input{width: 20em; text-align: center; margin-left: auto; margin-right: auto; padding: 8px;}
.input input{text-align: center; width: 100%; padding: 1em; box-sizing: border-box; margin:8px}

<loginForm.css>ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

<%@page import="member.model.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판</title>

<!-- 외부 스타일시트 적용 -->
<link type="text/css" rel="stylesheet" href="css/boardList.css">

</head>
<body>

	<h1 class="title">MVC를 게시판</h1>
	
	<!-- 로그인한 회원에 대한 환영인사 -->
	<!-- login 서블릿에서 Session 에 저장한 회원정보를 사용하기 [JSP의 내장객체 session 이용]: (표현언어)EL을 쓰면 조금 더 간결하게 가능 -->
	<% MemberVO member= (MemberVO)session.getAttribute("member");  %>
	
	<h4 class="message">
		<%=member.getUserName() %>님 환영합니다.
		
		<a href="../member/modifyForm.jsp" id="linkModify">회원정보수정</a>
		<a href="../logout" id="linkDelete">로그아웃</a>
	</h4>

</body>
</html>

<boardList.jsp>ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

@charset "UTF-8";

@font-face{
	font-family: 'jn';
	src: url("../../font/jn.ttf");
}

/*텍스트관련 스타일은 자식요소들에서 적용됨. 그래서 문서의 공통적인 적용을 하려면..*/
body{font-family: 'jn','Times New Roman', Times, serif; padding: 3em;}

.title{text-align: center;}
.message{text-align: center; line-height: 3em;}

#linkModify{
	position: absolute;
	right: 2em;
	top: 2em;
	
	color: black;
}

#linkModify:hover{color: blue;}

#linkDelete{
	position: absolute;
	right: 2em;
	top: 5em;
	
	color: black;
}
#linkDelete:hover{color: blue;}

<boardList.css>ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

package member.model;

import java.sql.Date;

public class MemberVO {
	
	private String userId;
	private String userPw;
	private String userName;
	private String userEmail;
	private Date regDate;
	
	
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserPw() {
		return userPw;
	}
	public void setUserPw(String userPw) {
		this.userPw = userPw;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserEmail() {
		return userEmail;
	}
	public void setUserEmail(String userEmail) {
		this.userEmail = userEmail;
	}
	public Date getRegDate() {
		return regDate;
	}
	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}
	
	
}

<MemberVO.java>ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

package member.model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

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

public class MemberDAO {
	
	//커넥션 풀을 이용하여 DB와 연결
	DataSource dataSource;
	
	public MemberDAO() {
		// TODO Auto-generated constructor stub
		try {
			Context context=new InitialContext();
			Context envContext= (Context)context.lookup("java:/comp/env");
			dataSource=(DataSource)envContext.lookup("jdbc/oracle");
			System.out.println("오라클 DBMS의 커넥션풀이 완성되었습니다. 언제든지 Connection을 꺼내 사용.");
			//커넥션 디비랑 연결하는 애
		} catch (NamingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}//..............................................................생성자
	
		public void insertMember(MemberVO vo) {
			//회원정보 추가DML insert (DB작업 후 연결)
			try {
				Connection conn=dataSource.getConnection();
				
				String sql="INSERT INTO TP01_MEMBER(USER_ID,USER_PW,USER_NAME,USER_EMAIL) VALUES(?,?,?,?)";
				PreparedStatement psmt=conn.prepareStatement(sql);
				psmt.setString(1, vo.getUserId());
				psmt.setString(2, vo.getUserPw());
				psmt.setString(3, vo.getUserName());
				psmt.setString(4, vo.getUserEmail());
				
				psmt.executeUpdate();
				
				psmt.close();
				conn.close();
				
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			
		}// --------------------------------------------------------------
		//셀렉트==get  //리턴값 멤버정보.
		public MemberVO getMember(MemberVO vo) {
			//회원정보 검색 DML select - where
			
			MemberVO member=null;
			
			
			try {
				Connection conn=dataSource.getConnection();
				
				String sql="SELECT * FROM TP01_MEMBER WHERE USER_ID=? AND USER_PW=?";
				PreparedStatement pstmt=conn.prepareStatement(sql);
				pstmt.setString(1, vo.getUserId());
				pstmt.setString(2, vo.getUserPw());
				
				ResultSet rs=pstmt.executeQuery();   //받아야함
				if(rs.next()) {
					member=new MemberVO();
					member.setUserId(rs.getString("USER_ID"));
					member.setUserPw(rs.getString("USER_PW"));
					member.setUserName(rs.getString("USER_NAME"));
					member.setUserEmail(rs.getString("USER_EMAIL"));
					member.setRegDate(rs.getDate("REG_DATE"));
				}
				
				rs.close();
				pstmt.close();
				conn.close();
				
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			//회원정보 객체 리턴
			
			return member;
		}//-----------------------------------------------------------회원정보 로그인
	
}

<MemberDAO.java> ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

package member.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;

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 javax.servlet.http.HttpSession;

import member.model.MemberDAO;
import member.model.MemberVO;

@WebServlet("/login")
public class LoginServlet extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
//		super.doPost(req, resp);
		
		//요청 데이터 인코딩,응답 MIME타입 및 인코딩설정
		req.setCharacterEncoding("utf-8");
		resp.setContentType("text/html; charset=utf-8");
		
		//1. 사용자의 요청처리
		String userId=req.getParameter("user_id");
		String userPw=req.getParameter("user_pw");
		
		//모델에게 전달할 데이터를 하나로 묶기   --전달할 값만 대입해 주면 됨..
		MemberVO vo=new MemberVO();
		vo.setUserId(userId);
		vo.setUserPw(userPw);
		
		//2. 비지니스 로직 -로그인 여부 요청.
		MemberDAO memberDao=new MemberDAO();
		MemberVO member=memberDao.getMember(vo);
		
		//3. 화면구현 [화면이동  - 포워드]
		if(member!=null) {
			//회원정보가 있으니 이제 게시판 페이지로 이동.
			//리다이렉트된 페이지에서도 회원정보를 사용해야 하기에 데이터를 바인딩하는 3개의 객체중 session 객체에 저장.
			HttpSession session=req.getSession();
			session.setAttribute("member", member);
			
			//게시판 관련 페이지와 서블릿은 무조건 하나의 서블릿에서 분배..그 시작점 서블릿의 url 매핑을 "/board"로 지정
			resp.sendRedirect("board");
		}else {
			//다시 로그인 페이지로 이동.. 다이얼로그(자바스크립트)로 다시 로그인하도록 안내문구 보여주면서 돌아가기
			//다이얼로그는 javascript 이니.. 응답을 js를 수행하도록..
			PrintWriter writer=resp.getWriter();
			writer.println("<!DOCTYPE html>");
			writer.println("<html>");
			writer.println("<head>");
		
			writer.println("<script>");
			writer.println("alert('아이디와 비밀번호를 확인하세요.');");
			writer.println("location.href='member/loginForm.jsp';");
			writer.println("</script>");
			
			writer.println("</head>");
			writer.println("</html>");
			
			
		}
		
		
	}
}

<LoginServlet.java> ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

package member.controller;

import java.io.IOException;

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 javax.servlet.http.HttpSession;

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
//		super.doGet(req, resp);
		
		//로그아웃 요청하였으니, 다시 로그인 페이지로 이동.. 하면서 세션에 저장한 회원정보 데이터도 제거
		HttpSession session=req.getSession();
		session.removeAttribute("member");
//		session.invalidate(); //연결종류  둘다 쓸 수 있음.
		
		resp.sendRedirect("member/loginForm.jsp");
	}

}

<LogoutServlet.java> ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

package member.controller;

import java.io.IOException;

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 member.model.MemberDAO;
import member.model.MemberVO;
@WebServlet("/signup")
//사용자의 요청을 처리하는 Contraller역할의 서블릿
public class SignupServlet extends HttpServlet{
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
//		super.doPost(req, resp);
		
		//요청 데이터의 인코딩, 응답에 대한 MIME 타입과 인코딩 - 한글깨짐 방지
		req.setCharacterEncoding("utf-8");
		resp.setContentType("text/html; charset=utf-8");
		
		//1. 요청데이터 처리
		String userId=req.getParameter("user_id");
		String userPw=req.getParameter("user_pw");
		String userName=req.getParameter("user_name");
		String userEmail=req.getParameter("user_email");
		
		//데이터를 하나로 묶는 VO클래스 객체 생성.
		MemberVO vo=new MemberVO();
		vo.setUserId(userId);
		vo.setUserPw(userPw);
		vo.setUserName(userName);
		vo.setUserEmail(userEmail);
		
		//2. model[MemberDAO] 에게 비지니스로직 요청 
		MemberDAO memberDao=new MemberDAO();
		//디비작성후 dao작업후 
		memberDao.insertMember(vo);
		
		//3.view 에게 화면구현 요청- 회원가입이 되었으니 로그인페이지로 이동
		resp.sendRedirect("member/loginForm.jsp");
	}

}

<SingnupServlet.java> ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

package board.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
//접속url중 ["/board"] 라는 주소로 접속하는 모든 요청에 대응하는 서블릿으로 매핑  - XML로 등록  ..WEB.XML
//RESTfull 방식이라고 부름.
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class BoardServlet extends HttpServlet{
	
	//RESTfull기법을 적용하였을 때의 여러 요청 구분 방식 ######################################################
	//GET:      /board                         --전제 게시글 리스트 검색       ==>HTML form요소 action="get"
	//GET:      /board/3                       --3번 NO에 해당하는 게시글 검색  ==>HTML form요소 action="get"
	//POST:     /board     [+VO data]          --새로운 게시글 INSERT (삽입)  ==>HTML form요소 action="post"
	//PUT:      /board/3    [+VO data]         --3번 NO에 해달하는 게시글 수정  ==>HTML form요소 action="post"
	//DELETE:   /board/3                       --3번 NO에 해달하는 게시글 삭제  ==>HTML form요소 action="get"
	
	//JavaScript의 AJAX를 사용하지 않으면, PUT, DELETE방식은 전달이 불가능함. 그래서 그런 경험을 간접적으로 경험하기 위해
	//<form>요소의 <input type="hidden" name="method">   ( hidden==사용자가 입력하지 않지만 보내지게)
	//으로 4가지 메소드방식을 전달 받을 것임.
	
	//그리고 글번호에 해당하는 경로 "/3"을 번호로 구분하려면 경로르 기반으로 코드를 작성해야 함. 
	//불편하지만 추후, Spring사용 시 경로구분 쉬움.
	//그래서 이 글번호도 <input type="hidden" name="board_no"> 타입으로 전달 받을 것임.
	//################################################################################################
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
//		super.doGet(req, resp);
		doHandle(req,resp);
		
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
//		super.doPost(req, resp);
		doHandle(req,resp);
		
	}
	
	void doHandle(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//요청 데이터 인코딩, 응답 MIME타입 및 인코딩
		req.setCharacterEncoding("utf-8");
		resp.setContentType("text/html; charset=utf-8");
		
		//1. 요청파라미터 요청 -RESTfull 기법을 위한 데이터들..
		String method=req.getParameter("method");
		String boardNo=req.getParameter("board_no");
		System.out.println("method:"+method);
		System.out.println("boardNo:"+boardNo);
		
		//컨트롤러 역할 - 요청별로 분배..
		if(method==null || method.equals("GET")) {  //글검색요청
			if(boardNo==null) {
				System.out.println("전체 게시글 리스트 검색을 검색요청하셨습니다.");
				
				//게시글 리스트검색은 model 역할의 클래스에게 요청
				
				//화면구현은 별도의 jsp 로 이동
				resp.sendRedirect("board/boardList.jsp");
			}else {
				System.out.println("상세 게시글 검색을 요청하셨습니다.");
			}
			
		}else if(method.equals("POST")) {  //새글 등록
			System.out.println("새로운 게시글 삽입을 요청하셨습니다.");
			
		}else if(method.equals("PUT")) {  //게시글 수정
			System.out.println("게시글 수정을 요청하셨습니다.");
			
		}else if(method.equals("DELETE")) {  //게시글 삭제
			System.out.println("게시글 삭제를 요청하셨습니다.");
			
		}
	}
}

<BoardServlet.java> ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

  <!-- 게시판의 시작점에 해당하는 서블릿 등록 -->
  <servlet>
  	<servlet-name>board</servlet-name>
  	<servlet-class>board.controller.BoardServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>board</servlet-name>
  	<url-pattern>/board</url-pattern>
  </servlet-mapping>
  
</web-app>

<web.xml 에서 등록 :: @WebServlert("/board")>ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

'ETC' 카테고리의 다른 글

RESTfull 기법  (0) 2023.11.16