본문 바로가기
Java Web Programming/4. JSP

[JSP] 회원관리 웹 어플리케이션2 - layout 두 가지 (로그인 + 회원가입 + 회원정보 수정 + 경로 + EL/JSTL + BootStrap + Model2 설계)

by 파프리카_ 2020. 9. 21.
728x90
반응형

'회원관리 웹 어플리케이션' 포스팅 에서 이어지는 포스팅으로 아래 기능이 추가되었다.

 

1. layout.jsp를 두 경우로 나눔

 1)login-layout.jsp - 로그인 시 보여지는 view 

 2)layout.jsp-로그인을 안 했을 때 보여지는 view

 

2.  login-layout.jsp 상태에서 회원정보 수정

- VO 정보와 session의 VO 정보 둘 다 수정

 


[ 프로그램 진행 원리 및 개요 ]

웹 페이지에서 동적으로 이동되는 부분(메인 화면)만 새로 업데이트하여 보여주기 위하여,

전체적인 layout을 잡아두고, 메인 화면에 기능에 따른 새로운 view(jsp)를 할당하여 동작하도록 한다.

 

1. layout 화면을 로그인/비로그인으로 나누어 제공

 


기능 2 : 로그인 상태에서 회워정보 수정 기능 

 


[ 구현 코드 ]  

Model

/MemberVO.java

package org.kosta.model;

public class MemberVO {
	private String id;
	private String password;
	private String name;
	private String address;
	
	
	public MemberVO() {
		super();
	}
	
	public MemberVO(String id, String password) {
		super();
		this.id = id;
		this.password = password;
	}

	public MemberVO(String id, String password, String name, String address) {
		super();
		this.id = id;
		this.password = password;
		this.name = name;
		this.address = address;
	}

	@Override
	public String toString() {
		return "MemberVO [id=" + id + ", password=" + password + ", name=" + name + ", address=" + address + "]";
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}
	
	
}

 

/MemberDAO.java

package org.kosta.model;

import javax.sql.DataSource;

import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;

/*
 *  Database Connection Pool 객체를 생성해 공유하는 클래스 
 *  DBCP -> 시스템 성능 향상을 위해 DB 컨넥션을 생성, 소멸시키지 않고
 *  		   미리 생성한 컨넥션을 빌려주고 반납하도록 한다. 
 *  javax.sql.DataSource Interface 타입으로 dbcp를 관리한다 
 *  이유는 WAS 가 변경되면 DBCP도 변경될 수 있으므로 추상화된 인터페이스 타입으로
 *  관리하는 것이 유지보수에 유리하다 
 */
public class DataSourceManager {
	private static DataSourceManager instance=new DataSourceManager();
	private DataSource dataSource;
	private DataSourceManager() {
		// was tomcat에서 제공하는 dbcp를 생성해서 사용한다 
		BasicDataSource dbcp=new BasicDataSource();
		dbcp.setDriverClassName("oracle.jdbc.OracleDriver");
		dbcp.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:xe");
		dbcp.setUsername("scott");
		dbcp.setPassword("tiger");
		dbcp.setInitialSize(3);//처음 로드될 때 생성해 놓을 컨넥션 수 
		dbcp.setMaxTotal(10);//최대 컨넥션 수 : 기본은 8 
		this.dataSource=dbcp;
	}
	public static DataSourceManager getInstance() {
		return instance;
	}
	public DataSource getDataSource() {
		return dataSource;
	}
}

View

 

[ template ]

 

/index.jsp 

index를 실행하면 <jsp:forward> 방식으로 home.jsp로 간다

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<jsp:forward page="front">
	<jsp:param value="home" name="command"/>
</jsp:forward>

 

/home.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

[ CSS ]

 

/myhome.css

@charset "UTF-8";
.header {
	/*문자 정렬 왼쪽*/
	text-align: left;
	height: 70px;
}

.main {
	text-align: center;
	height: 500px;
}

.footer {
	text-align: center;
	height: 10px;
}

--  기능 1: id로 회원 정보 찾기

 

/findbyid-form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%-- findbyid-form.jsp
		ㅣ
	FindMemberByIdController
	    ㅣ
	findbyid-fail.jsp에서는 alert후 home으로 이동
	(해당 파일로 forward)
	findbyid-ok.jsp에서는 layout이 적용되어야 함
--%>
<form action="front">
<input type="hidden" name="command" value="findMemberById">
아이디 <input type="text" name="id" required="required">
<input type="submit" value="검색">
</form>

 

/findbyid-ok.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
검색 결과 <br>
아이디 : ${param.id}<br>
이름 : ${requestScope.vo.name}<br>
주소 : ${requestScope.vo.address}<br>

 

/findbyid-fail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<script type="text/javascript">
	alert("${param.id} 에 해당하는 회원정보가 없습니다!")
	location.href = "front?command=home"
</script>

-- 기능 2 : 회원 가입 기능

 

/register-form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
	command-reigster -- RegisterController -- MemberDAO : register
							 	ㅣ
							 	ㅣredirect
							 	ㅣ
				      RegisterResultController
				      			ㅣ forward 
				      			ㅣ : forward일때만 layout으로 갈 수 있음
					  member/register-result.jsp 
					  (레이아웃이 적용되어야 함)
						
 --%>
<form action="${pageContext.request.contextPath}/front" method="post">
	<input type="hidden" name="command" value="register">
	아이디 <input type="text" name="id" required="required"><br>
	패스워드 <input type="password" name="password" required="required"><br>
	이름 <input type="text" name="name" required="required"><br>
	주소 <input type="text" name="address" required="required"><br><br>
	<input type="submit" value="회원가입">
</form>

 

/register-result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
${requestScope.vo.name}님 회원가입이 완료되었습니다.

-- 기능 3 : 로그인 + 로그아웃 기능 (로그인 실패 페이지만 필요)

 

/login-fail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<script type="text/javascript">
	alert("로그인 실패!");
	location.href = "front?command=home"
</script>

-- 기능 4 : 회원 정보 수정 기능 

 

sessionScope를 쓸 때에는 JSP 선언부에 session="false"가 있으면 안된다 !

 

/update-form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<form action="${pageContext.request.contextPath}/front" method="post">
	<input type="hidden" name="command" value="updateMember">
	아이디 <input type="text" name="id" value="${sessionScope.mvo.id}" readonly="readonly"><br>
	패스워드 <input type="password" name="password" value="${sessionScope.mvo.password}" required="required"><br>
	이름 <input type="text" name="name" value="${sessionScope.mvo.name}" required="required"><br>
	주소 <input type="text" name="address" value="${sessionScope.mvo.address}" required="required"><br><br>
	<input type="submit" value="수정하기">
</form>

 

/update-result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<strong>회원정보 수정 완료!</strong><br><br>
아이디 : ${sessionScope.uvo.id}<br>
이름 : ${sessionScope.uvo.name}<br>
주소 : ${sessionScope.uvo.address}<br>

Controller

/Controller.java

package org.kosta.controller;

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

public interface Controller {
	public String execute(HttpServletRequest request,
			HttpServletResponse response) throws Exception;
}

 

/ HandlerMapping.java

package org.kosta.controller;

public class HandlerMapping {
	private static HandlerMapping instance=new HandlerMapping();
	private HandlerMapping() {}
	public static HandlerMapping getInstance() {
		return instance;
	}
	public Controller create(String command) {
		Controller controller=null;
		if(command.contentEquals("home"))
			controller=new HomeController();
		else if(command.contentEquals("findMemberByIdForm"))
			controller=new FindMemberByIdFormController();
		else if(command.contentEquals("findMemberById"))
			controller=new FindMemberByIdController();
		else if(command.contentEquals("registerForm"))
			controller=new RegisterFormController();
		else if(command.contentEquals("register"))
			controller=new RegisterController();
		else if(command.contentEquals("register-result"))
			controller=new RegisterResultController();
		else if(command.contentEquals("login"))
			controller=new LoginController();
		else if(command.contentEquals("logout"))
			controller=new LogoutController();
		else if(command.contentEquals("updateMemberForm"))
			controller=new UpdateMemberFormController();
		else if(command.contentEquals("updateMember"))
			controller=new UpdateMemberController();
		else if(command.contentEquals("updateMember-result"))
			controller=new UpdateMemberResultController();
		return controller;
	}
}

 

/DispatcherServlet.java

handleRequest method 작동 방식

1. 에러(예외) 발생 시, 콘솔에 메세지 발생 경로 출력 후,  error.jsp로  redirect 방식으로 view로 이동한다.

2. 클라이언트가 전송한 command 정보를 받는다.

3. HandlerMapping 을 이용해 개별 컨트롤러 객체를 컨트롤러 인터페이스 타입으로 반환받는다.

4. 개별 컨트롤러를 실행한다.

5. 실행 후 반환된 String url 정보를 이용해,

     forward 방식 or redirect 방식으로 view로 이동해 응답하게 한다.

+ 각 단계에서 어디서 에러가 났는지 알 수 있도록 단계 별로 console에 print 되도록 해준다

package org.kosta.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;

/**
 * Servlet implementation class DispatcherServlet
 */
@WebServlet("/front")
public class DispatcherServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
  
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.handleRequest(request, response);
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		this.handleRequest(request, response);
	}
	/*	1. 에러 발생시 error.jsp로 redirect 한다
	 *  2. client가 보낸 command를 받는다 
	 *  3. command를 이용해 HandlerMapping의 create를 호출 , 컨트롤러를 반환받는다 
	 *  4. 컨트롤러를 실행한다 
	 *  5. 컨트롤러가 실행 한 후 반환하는 String 정보를 이용해 
	 *      forward 또는 redirect 방식으로 응답하도록 view로 이동시킨다. 
	 */
	protected void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			String command=request.getParameter("command");
		//	System.out.println("command:"+command);
			Controller controller=HandlerMapping.getInstance().create(command);
		//	System.out.println("controller:"+controller);
			String url=controller.execute(request, response);
		//	System.out.println("url:"+url);
			if(url.startsWith("redirect:"))
				response.sendRedirect(url.substring(9));
			else
				request.getRequestDispatcher(url).forward(request, response);
		}catch (Exception e) {
			e.printStackTrace(); // 예외 메세지와 발생 경로를 모두  콘솔에 출력한다 
			response.sendRedirect("error.jsp");
		}
	}
}

 


---  기능 0 : index.jsp에서 실행하면,  로그인 여부 판단에 따라 서로 다른 layout으로 이동하는 Controller

(request.setAttribute를 통해 url에 home.jsp를 할당하여, home 정보를 메인화면에 할당)

 

/HomeController.java

package org.kosta.controller;

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

public class HomeController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) 
			throws Exception {
		/*
		 * 로그인 사용자와 로그인하지 않은 사용자를 구분하여 home 화면을 다르게 제공한다.
		 */
		String url = null;

		HttpSession session = request.getSession(false);

		if (session != null && session.getAttribute("mvo") != null)
			// 로그인 사용자
			url = "/template/login-layout.jsp";
		else // 로그인 하지 않은 사용자
			url = "/template/layout.jsp";

		// 웹 디자인 레이아웃이 적용된 화면으로 응답하기 위해
		// template/layout.jsp에 있는 아래 코드 부분에 화면 정보를 할당한 후
		// <c:import url="${requestScope.url}">
		// layout.jsp로 forward 한다
		request.setAttribute("url", "/home.jsp");

		return url;
	}
}

---  기능 1 : 아이디로 회원정보 조회 Controller

forward 방식의 경우 Form -> layout view로 이동 순으로 진행한다.

 

/FindMemberByIdFormController.java

package org.kosta.controller;

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

public class FindMemberByIdFormController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		request.setAttribute("url", "/member/findbyid-form.jsp");
		// 레이아웃 적용
		return "/template/login-layout.jsp";
	}

}

 

/FindMemberByIdController.java

package org.kosta.controller;

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

import org.kosta.model.MemberDAO;
import org.kosta.model.MemberVO;

public class FindMemberByIdController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) 
			throws Exception {
		String id = request.getParameter("id");
		MemberVO vo = MemberDAO.getInstance().findMemberById(id);
		if (vo != null) {
			request.setAttribute("vo", vo);
			request.setAttribute("url", "/member/findbyid-ok.jsp");
		} else {
			//레이아웃 적용이 필요 없으므로
			//바로 findbyid-fail.jsp로 감(javascript 실행만 필요)
			return "/member/findbyid-fail.jsp";
		}
		return "/template/login-layout.jsp";
	}

}

---  기능 2 :  회원가입 기능 Controller

redirect 방식의 경우 form 에서 바로 view로 이동하게되면 회원가입이 여러번 진행되어 오류가 발생할 수 있으므로,

form에서 view에 앞서 controller로 이동시켜야한다.

그러므로, form -> 동작 -> layout view로 이동한다.

 

/RegisterFormController.java

package org.kosta.controller;

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

public class RegisterFormController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) 
			throws Exception {
		//layout이 적용된 회원가입폼 화면이 응답하게 한다
		request.setAttribute("url", "/member/register-form.jsp");
		return "/template/layout.jsp";
	}

}

 

/RegisterController.java

package org.kosta.controller;

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

import org.kosta.model.MemberDAO;
import org.kosta.model.MemberVO;

public class RegisterController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) 
			throws Exception {
		
		/* < forwarding 방식 >
		 * System.out.println("회원 가입 처리"); 
		 * request.setAttribute("url","/member/register-result.jsp");
		 * return "/template/layout.jsp";
		 * 
		 * forwarding 방식은 회원가입에는 적절하지 않다.
		 * 그 이유는 forward 방식으로 응답하면 사용자가 재동작시킬 경우
		 * 다시 가입을 시도하기 때문이다!
		 * 
		 * 그렇기 때문에 회원가입과 같은 DB에 INSERT, UPDATE, DELETE하는
		 * 경우에는 redirect 방식이 적합하다.
		 */
		
		String id = request.getParameter("id");
		String password = request.getParameter("password");
		String name = request.getParameter("name");
		String address = request.getParameter("address");
		
		MemberVO vo = new MemberVO(id, password, name, address);
		
		MemberDAO.getInstance().register(vo);
		
		//RegisterResultController로 보내기 위해 
		//command에 register-result를 적어준다.
		// + id를 넘겨주기 위해 쿼리스트링 방식으로 id를 넘겨준다
		return "redirect:front?command=register-result&id="+id;
	}

}

 

/RegisterResultController.java

package org.kosta.controller;

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

import org.kosta.model.MemberDAO;
import org.kosta.model.MemberVO;

public class RegisterResultController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		//RegisterController에서 보낸 id를 getParameter로 받아올수 있다
		String id = request.getParameter("id");
		//이 id를 이용해 DAO에 있는 method를 통해 정보를 받아준다
		MemberVO vo = MemberDAO.getInstance().findMemberById(id);
		
		request.setAttribute("vo", vo);
		request.setAttribute("url", "/member/register-result.jsp");

		return "/template/layout.jsp";
	}
}

---  기능 3 :  로그인 + 로그아웃 기능 Controller

 

/LoginController.java

package org.kosta.controller;

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

import org.kosta.model.MemberDAO;
import org.kosta.model.MemberVO;

public class LoginController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) 
			throws Exception {
		String id = request.getParameter("id");
		String password = request.getParameter("password");
		MemberVO vo = new MemberVO(id, password);
		MemberVO mvo = MemberDAO.getInstance().login(vo);
		
		if (mvo == null) {
			return "/member/login-fail.jsp";
		} else {
			HttpSession session = request.getSession();
			session.setAttribute("mvo", mvo);
			request.setAttribute("url", "/member/login-ok.jsp");
			return "/template/login-layout.jsp";
		}
	}

}

 

/LogoutController.java

package org.kosta.controller;

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

public class LogoutController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		
		HttpSession session = request.getSession(false);
		
		//로그인 정보가 있을때
		if (session != null)
			session.invalidate(); //로그아웃
			
		return "front?command=home";
	}

}

--  기능 4 : 회원정보 수정  Controller 

 

/UpdateMemberFormController.java

package org.kosta.controller;

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

public class UpdateMemberFormController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		//login-layout의 메인화면 부분에 update-form.jsp을 보냄
		request.setAttribute("url", "/member/update-form.jsp");
		return "/template/login-layout.jsp";
	}

}

 

/UpdateMemberController.java

session정보의 vo객체와 DAO를 통해 받아온 기존에 존재하던 vo객체 둘 다 수정해준다. 

package org.kosta.controller;

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

import org.kosta.model.MemberDAO;
import org.kosta.model.MemberVO;

public class UpdateMemberController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		String id = request.getParameter("id");
		String password = request.getParameter("password");
		String name = request.getParameter("name");
		String address = request.getParameter("address");
		MemberVO uvo = new MemberVO(id, password, name, address);
		
		//MemberVO 정보 수정
		MemberDAO.getInstance().updateMember(uvo);
		
		//session의 MemberVO 정보 수정
		HttpSession session = request.getSession(false);
		if (session != null && session.getAttribute("mvo") != null) {
			//session에 회원정보 업데이트 
			session.setAttribute("uvo", uvo);
			return "redirect:front?command=updateMember-result";
		} else {
			return "redirect:front?command=home";
		}
	}

}

 

/UpdateMemberResultController.java

package org.kosta.controller;

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

public class UpdateMemberResultController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) 
			throws Exception {
		request.setAttribute("url", "/member/update-result.jsp");
		return "/template/login-layout.jsp";
	}

}

 


[ 브라우저 화면 ] 

 

> Home (home.jsp)

 

> 1. 회원 검색 폼

 

> 1-1. 회원 검색 : 존재하는 아이디 검색했을 때, (findbyid-ok.jsp)

 

> 1-2. 회원 검색 :존재하지 않는 아이디 검색했을 때, (findbyid-fail.jsp)

> 2-1. 회원 가입 폼

 

>2-2. 회원 가입 성공 결과

 

> 3-1. 로그인 성공 시,

 

>  3-2. 로그인 실패 시 -> index.jsp

>  4-1. 회원 정보 수정 폼

 

> 4-2. 회원 정보 수정 후

728x90
반응형