복습

전체 흐름

 

Service 클래스

- 공통적인 내용들을 Action 이라는 인터페이스에 작성, 추상메소드 execute() 가 있다

- 각각의 클래스들은 인터페이스 Action 을 상속함, 반드시 추상메소드 execute() 를 오버라이딩 해야함

- 클라이언트의 요청을 실제로 처리

- DAO 와 함께 실제 DB 쪽에 데이터를 처리해주는 Model 이라고 불린다

 

- DB에서 검색한 결과를 DAO 에서 Service 클래스로 리턴함

- Service 클래스에서 돌려받은 객체를 공유설정함

- View 페이지에서 공유설정된 값을 EL + JSTL 으로 출력한다

 

Controller 클래스

- HttpServlet 클래스를 상속받는다, doPost(), doGet() 메소드를 오버라이딩 해야함

- WebServlet 어노테이션 이름값이 하나면 한곳에서 온 요청만 받을 수 있으므로 Controller 클래스를 여러개 만들어야한다

- WebServlet 어노테이션 이름값을 패턴을 지정해서 패턴에 맞으면 다 여기로 오도록 함

- 그 후 폼의 action 값들을 패턴에 맞게 지정한다, 그럼 Contorller 클래스로 찾아갈 수 있음

- 다른 웹사이트의 URL 주소를 보면 확장자가 보인다 ex) .do, .naver


회원관리 프로그램 : Controller 클래스 (이어서)

- MemberController.java (수정 전 1)

package 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 MemberController
 */
@WebServlet("*.do")	// do 확장자
public class MemberController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	// doGet(), doPost() 메소드에서 공통적인 작업을 처리하는 메소드
	protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String requestURI = request.getRequestURI();
		String contextPath = request.getContextPath();
		String command = requestURI.substring(contextPath.length());
		
		System.out.println("requestURI : " + requestURI); // requestURI : /model2member/Login.do
		System.out.println("contextPath : " + contextPath); // contextPath : /model2member
		System.out.println("command : " + command); // command : /Login.do
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("get");
		doProcess(request, response);	// doProcess() 호출
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("post");
		doProcess(request, response);	// doProcess() 호출
	}

}

- Controller 클래스에서 매개변수로 받은 request, response 객체를 Service 클래스로 넘어갈때도 전달한다

- doPost(), doGet() 에서 받은 request, response -> doProcess() 호출시 넘겨줌 -> Service 클래스로 갈때도 넘겨줌

- doProcess() 에도 넘겨줘야 거기서 request.getRequestURI() 와 request getContextPath() 메소드를 사용가능

 

doProcess() 안의 내용 (MemberController.java 부분)

	// doGet(), doPost() 메소드에서 공통적인 작업을 처리하는 메소드
	protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String requestURI = request.getRequestURI();
		String contextPath = request.getContextPath();
		String command = requestURI.substring(contextPath.length());
		
		System.out.println("requestURI : " + requestURI); // requestURI : /model2member/Login.do
		System.out.println("contextPath : " + contextPath); // contextPath : /model2member
		System.out.println("command : " + command); // command : /Login.do
	}

- command 에 저장되는 값에 구체적으로 어떤 요청이름기값으로 Controller 클래스로 왔는지 확인 가능

- 즉, command 에 저장된 값으로 어디서 요청이 왔는지 확인 가능하다

- command 값을 보고 어떤 서비스 클래스로 보낼지 결정한다

+ substring(13) 은 13 인덱스부터 끝까지를 자른다

 

- 결과 확인 1

- loginform.jsp form 태그

	<form method="post" action="<%=request.getContextPath() %>/Login.do">

 

- loginform.jsp 파일을 실행해서 '로그인' 을 눌러보자

+ 해당 Service 클래스 이름도 요청 이름값과 똑같이 작성할 것, Login.java

 

- 결과 확인 2

- memberform.jsp form 태그

<form method="post" action="<%=request.getContextPath() %>/MemberInsert.do">

- memberform.jsp 파일을 실행해서 '회원가입' 을 눌러보자

- 요청 이름값이 command 변수에 저장된다

+ 해당 Service 클래스 이름도 요청 이름값과 똑같이 작성할 것, MemberInsert.java

 

실행 순서

1. loginform.jsp 또는 memberform.jsp 에서 action 태그로 지정된 곳을 따라 Controller 클래스 도착

2. post 방식으로 요청했으므로 오버라이딩 된 doPost() 실행됨, doProcess() 가 다음으로 실행됨

3. 3개의 변수값이 구해짐

- 최종적으로는 요청 이름값이 저장된 command 변수의 값이 필요하다

- 어떤 서비스 클래스로 보낼지 command 값을 보고 결정

 

회원관리 프로그램 : Service 클래스 1

- Service 클래스를 통일성 있게 설계하기 위해 부모가 될 인터페이스 Action 먼저 만들기

- 인터페이스 Action 을 만들고 안에는 추상메소드 execute() 만들기

- Service 에서 DAO 로 넘어가야한다

 

+ ActionForward 클래스

- 이 클래스에서 어떤 방식으로 포워딩 할지, 어디로 포워딩 할지 결정해줌

- redirect 변수는 포워딩 방식을 설정, path 는 포워딩할 페이지명 설정

- request 객체로 공유가 되면 포워딩 하는 방법 2가지가 있다

- request 객체로 공유가 되었을때는 반드시 dispatcher 방식으로 포워딩되어야 뷰페이지에 출력 가능

 

부모 인터페이스 만들기

- 이제 service 패키지를 만들고 인터페이스 Action 을 만들자

- 현재까지 Action 인터페이스

- Action.java

package service;

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

public interface Action {
	
	// 추상 메소드
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

- 리턴자료형은 아직 만들지 않은 ACtionForward 로 한다

- Controller 클래스의 doProcess() 의 매개변수 request, response 를 그대로 execute() 의 매개변수에 복사

- 추상메소드 execute() 는 형식만 있다

 

ActionForward 클래스 만들기

- ActionForward.java

package service;

public class ActionForward {
	
	private boolean redirect;	// 포워딩 방식 설정
	private String path;	// 포워딩 페이지명 설정
	
	public boolean isRedirect() {
		return redirect;
	}
	public void setRedirect(boolean redirect) {
		this.redirect = redirect;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	
}

- Service 패키지 안에 ActionForward 클래스 만들기

1. 포워딩 방식을 결정할 변수 redirect 정의,  dispatcher, redirect 방식 중 어느 것으로 할지 true, false 로 결정

2. 포워딩할 페이지명이 저장될 변수 path 를 정의

- 두 변수는 private 으로 설정

3. getter, setter 메소드 만들기

+ 이클립스가 redirect 변수의 getter 메소드를 자동으로 만들때 getRedirect() 가 아니라 isRedirect() 로 만들었음을 유심히 보기

- Service 클래스에서 값을 처리하고 View 페이지로 가기 전에 이 ActionForward 로 포워딩 방식, 포워딩 페이지명을 결정

 

- 다시 Controller 클래스로 돌아와서 Service 클래스로 넘겨주는 작업을 하자

- MemberController.java  (수정 전 2)

package controller;

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 service.Action;
import service.ActionForward;
import service.MemberInsert;

/**
 * Servlet implementation class MemberController
 */
@WebServlet("*.do")	// do 확장자
public class MemberController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	// doGet(), doPost() 메소드에서 공통적인 작업을 처리하는 메소드
	protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String requestURI = request.getRequestURI();
		String contextPath = request.getContextPath();
		String command = requestURI.substring(contextPath.length());
		
		System.out.println("requestURI : " + requestURI); // requestURI : /model2member/Login.do
		System.out.println("contextPath : " + contextPath); // contextPath : /model2member
		System.out.println("command : " + command); // command : /Login.do
		
		Action action = null;
		ActionForward forward = null;
		
		// 회원가입
		if(command.equals("/MemberInsert.do")) {
			try {
				action = new MemberInsert();
				forward = action.execute(request, response);
				
			} catch (Exception e){
				e.printStackTrace();
			}
		}
		
		// 포워딩 처리
		if(forward != null) {
			if(forward.isRedirect()) {	// redirect 방식으로 포워딩
				response.sendRedirect(forward.getPath());
			} else {				// dispatcher 방식으로 포워딩
				RequestDispatcher dispatcher = 
						request.getRequestDispatcher(forward.getPath());
				dispatcher.forward(request, response);
			}
		}
		
	} // doProcess() end

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("get");
		doProcess(request, response);	// doProcess() 호출
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("post");
		doProcess(request, response);	// doProcess() 호출
	}

}

- 모두 doProcess() 안에서 작성한다

- service 패키지 안의 Action 인터페이스 객체 action 를 만들고 null 로 초기화

- service 패키지 안의 ActionForward 클래스 객체 forward 를 만들고 null 로 초기화

- 다음은 요청에 따라 적절한 Service 클래스로 넘기기

- 마지막 부분에서 포워딩 처리를 한다, DAO -> Service -> Controller 로 돌아올때 포워딩 처리함

 

Service 클래스로 전달 (MemberController.java 부분)

		// 회원가입
		if(command.equals("/MemberInsert.do")) {
			try {
				action = new MemberInsert();
				forward = action.execute(request, response);
				
			} catch (Exception e){
				e.printStackTrace();
			}
		}

- Controller 클래스는 어떤 Service 클래스로 넘겨줄건지 결정

- command 값, 즉 요청 이름값이 "/MemberInsert" 면 회원가입을 처리하는 MemberInsert 클래스로 객체 action 생성

- 왼쪽은 부모 인터페이스, 오른쪽은 상속받는 구현 클래스가 왔다, 업캐스팅을 하고 있음

- action 객체를 통해 MemberInsert() 클래스의 오버라이딩된 메소드인 execute() 를 실행하고 ActionForward 객체 forward 로 리턴받음

- 해당 클래스 MemberInsert 의 객체를 만들고 execute() 를 실행하므로써 그 Service 클래스 MemberInsert 로 가는 것임

+ 메소드 오버라이딩이 되면 오버라이딩 된 메소드만 실행된다

- execute() 를 호출하며 매개변수로는 doGet(), doPost() 의 매개변수인 request, response 를 전달함

+ try-catch 예외처리 해야한다

* MemberInsert 클래스는 아래에서 구현한 회원가입 처리 Service 클래스이다.

 

포워딩 처리 (MemberController.java 부분)

		// 포워딩 처리
		if(forward != null) {
			if(forward.isRedirect()) {	// redirect 방식으로 포워딩
				response.sendRedirect(forward.getPath());
			} else {				// dispatcher 방식으로 포워딩
				RequestDispatcher dispatcher = 
						request.getRequestDispatcher(forward.getPath());
				dispatcher.forward(request, response);
			}
		}

- Controller 클래스에서는 포워딩 처리도 한다

- forward 객체는 한번 Service 클래스로 갔다오면 null 이 아니게 됨

- forward.isRedirect() 는 true, false 를 돌려줌, true면 redirect 방식 포워딩, false 면 diepacher 방식으로 포워딩 하기로 함

- getPath() 메소드로 포워딩할 페이지 불러오기

 


회원관리 프로그램 : 회원가입 기능

- 이제 잠시 Controller 클래스는 두고, 회원가입 기능을 먼저 구현하자

- 먼저 회원가입 폼 memberform.jsp 를 보자

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>

<script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script>
<script>
	function openDaumPostcode() {
		new daum.Postcode({
			oncomplete : function(data) {
				// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
				// 우편번호와 주소 정보를 해당 필드에 넣고, 커서를 상세주소 필드로 이동한다.
//				document.getElementById('join_zip1').value = data.postcode1;
//				document.getElementById('join_zip2').value = data.postcode2;
				document.getElementById('post').value = data.zonecode;
				document.getElementById('address').value = data.address;
				
			}
		}).open();
	}
</script>


<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="<%=request.getContextPath() %>/member/member.js"></script>

</head>
<body>

<form method="post" action="<%=request.getContextPath() %>/MemberInsert.do"> 
<table border=1 width=500 align=center>
	<caption>회원 가입</caption>
	<tr><td>ID</td>
		<td><input type=text autofocus="autofocus" id="id" name="id">
			<input type=button value="ID중복검사" id="idcheck">
			<div id="myid"></div>
		</td>
	</tr>
	<tr><td>비밀번호</td>
		<td><input type=password id="passwd" name="passwd"></td>
	</tr>
	<tr><td>성명</td>
		<td><input type=text id="name" name="name"></td>
	</tr>
	<tr><td>주민번호</td>
		<td><input type=text size=6 maxlength=6 id="jumin1" name="jumin1">-
			<input type=text size=7 maxlength=7 id="jumin2" name="jumin2">
		</td>
	</tr>
	<tr><td>E-Mail</td>
		<td><input type=text size=10 id="mailid" name="mailid">@
		    <input type=text size=10 id="domain" name="domain">
		    <select id="email">
		    	<option value="">직접입력</option>
		    	<option value="naver.com">네이버</option>
		    	<option value="daum.net">다음</option>
		    	<option value="nate.com">네이트</option>
		    	<option value="gmail.com">gmail</option>
		    </select>		    
		 </td>
	</tr>
	<tr><td>전화번호</td>
		<td><input type=text size=4 id="tel1" name="tel1" maxlength=4>-
			<input type=text size=4 id="tel2" name="tel2" maxlength=4>-
			<input type=text size=4 id="tel3" name="tel3" maxlength=4>
		</td>
	</tr>
	<tr><td>핸드폰</td>
		<td><select id="phone1" name="phone1">
				<option value="">번호선택</option>
				<option value="010">010</option>
				<option value="011">011</option>
				<option value="016">016</option>
				<option value="018">018</option>
				<option value="019">019</option>
			</select>-
			<input type=text size=4 id="phone2" name="phone2" maxlength=4>-
			<input type=text size=4 id="phone3" name="phone3" maxlength=4>
		</td>
	</tr>
	<tr><td>우편번호</td>
		<td><input type=text size=5 id="post" name="post">
			<input type=button value="우편번호검색" 
			       onClick="openDaumPostcode()">
		</td>
	</tr>
	<tr><td>주소</td>
		<td><input type=text size=45 id="address" name="address"></td>
	</tr>
	<tr><td>성별</td>
		<td>
			<input type=radio id="male" name="gender" value="남자">남자
			<input type=radio id="female" name="gender" value="여자">여자
		</td>
	</tr>
	<tr><td>취미</td>
		<td>
			<input type="checkbox" id="h1" name="hobby" value="공부" checked>공부
			<input type="checkbox" id="h2" name="hobby" value="게임">게임
			<input type="checkbox" id="h3" name="hobby" value="등산">등산
			<input type="checkbox" id="h4" name="hobby" value="낚시">낚시
			<input type="checkbox" id="h5" name="hobby" value="쇼핑">쇼핑
		</td>
	</tr>	
	<tr><td>자기소개</td>
		<td>
			<textarea id="intro" name="intro" rows="5" cols="50" placeholder="자기소개를 100자 이내로 입력하세요"></textarea>
		</td>
	</tr>
	<tr><td colspan=2 align=center>
			<input type=submit value="회원가입">
			<input type=reset value="취소">
		</td>
	</tr>		
</table>
</form>


</body>
</html>

 

유효성 검사를 하는 자바스크립트 불러오기 경로 (memberform.jsp 부분)

<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="<%=request.getContextPath() %>/member/member.js"></script>

- Controller 클래스에 의해 왔다갔다 하면 상대경로이기 때문에 이 경로를 잘 못찾아갈 수도 있다

- 이땐 위의 코드처럼 프로젝트명을 적고 나머지는 WebContent 폴더 기준으로 하위폴더를 모두 쓰고 파일명을 적기

+ request.getContextPath() 메소드는 프로젝트 명을 구해줌 ex) /model2member

 

form 의 action 태그 (memberform.jsp 부분)

<form method="post" action="<%=request.getContextPath() %>/MemberInsert.do">

- post 방식으로 입력양식의 값들을 전송한다

- model 2 에서는 파일이 아닌 무조건 Controller 클래스로 찾아가야한다, 프로젝트명을 앞에 붙이면 Controller 클래스를 잘 찾아감

- 배포가 되면 프로젝트가 URL 경로상에서 빠지므로 프로젝트명을 직접 적는 것이 아닌 request.getContextPath() 사용

 

회원관리 프로그램 : 회원가입 Service 클래스

- 실제 회원가입 요청을 처리하는 MemberInsert.java 파일을 만들자

- 회원가입 폼의 요청이름값과 동일하게 설정

- service 패키지에 MemberInsert.java 클래스 생성

package service;

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

import dao.MemberDAO;
import model.MemberDTO;

public class MemberInsert implements Action{

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		System.out.println("MeberInsert");
		
		request.setCharacterEncoding("utf-8");
		
		MemberDTO member = new MemberDTO();
		member.setId(request.getParameter("id"));
		member.setPasswd(request.getParameter("passwd"));
		member.setName(request.getParameter("name"));
		member.setJumin1(request.getParameter("jumin1"));
		member.setJumin2(request.getParameter("jumin2"));
		member.setMailid(request.getParameter("mailid"));
		member.setDomain(request.getParameter("domain"));
		member.setTel1(request.getParameter("tel1"));
		member.setTel2(request.getParameter("tel2"));
		member.setTel3(request.getParameter("tel3"));
		member.setPhone1(request.getParameter("phone1"));
		member.setPhone2(request.getParameter("phone2"));
		member.setPhone3(request.getParameter("phone3"));
		member.setPost(request.getParameter("post"));
		member.setAddress(request.getParameter("address"));
		member.setGender(request.getParameter("gender"));
		
		String[] hobby = request.getParameterValues("hobby");
		String h = "";
		for(String h1 : hobby) {
			h += h1 + "-";	// h = "공부-게임-"
		}
		member.setHobby(h);
		member.setIntro(request.getParameter("intro"));
		
		MemberDAO dao = MemberDAO.getInstance();
		int result = dao.insert(member);	// 회원가입
		
		if(result == 1) System.out.println("회원가입 성공");
		
		ActionForward forward = new ActionForward();
		forward.setRedirect(false); // dispatcher 방식으로 포워딩
		forward.setPath("./member/loginform.jsp");	// 포워딩할 파일명
		
		return forward;
	}
}

<회원가입 Service 클래스 형식, 전체적인 흐름>

- 부모 인터페이스인 Action 인터페이스를 상속받기, 이클립스 자동 기능으로 execute() 를 메소드 오버라이딩 하기

- request 객체는 Controller 클래스의 getPost() -> getProcess() -> Service 클래스의 execute() 로 넘어왔다

- 매개변수를 통해 Controller 클래스의 request 객체가 그대로 넘어왔으므로, 폼에서 Controller 클래스로 넘겨준 form 의 각종 입력양식의 값들을 여기 Service 클래스에서 request.getParamter() 로 가져올 수 있다

- 필드값을 설정한 ActionForward 객체를 execute() 를 호출한 Controller 클래스에 돌려줌

 

<회원가입 Service 클래스 작성 순서>

1. 먼저 post 방식으로 한글값이 넘어올 수 있으므로 한글값 인코딩을 설정한다

2. DTO 객체를 만들고 setter 메소드로 값을 세팅

- jsp 에서 useBean, setProperty 로 DTO 객체 생성하고 값을 세팅했던 코드에 해당함

- 이때 DTO 개체에 설정하는 값은 폼-> 컨트롤러-> 서비스 클래스로 넘어온 request 객체를 사용해서 request.getParamter() 로 폼 입력양식의 입력값을 가져와서 설정

- 취미는 2개이상 선택해야하는 양식이므로 값을 getParamterValues() 로 받고 여러개의 값을 하이픈으로 결합해서 저장

+ Spring 에선 일일히 값을 전달하지 않아도 어노테이션으로 한번에 처리 가능

3. DAO 객체를 생성하고 회원가입 insert 를 하는 DAO 의 insert() 메소드 호출

- 매개변수로 값을 설정한 DTO 객체를 넘긴다

- insert() 가 잘 수행되었으면 1 을 리턴한다

4. insert() 가 끝난다음엔 Service -> 다시 execute() 를 호출한 Controller 로 돌아가야한다

- 이때 Controller 로 ActionForward 객체를 리턴해야한다

- 리턴하기 전에 어떤 방식으로 포워딩할지, 어느 파일로 포워딩할지를 setRedirect(), setPath() 로 설정

- 지금은 request 객체로 공유를 설정하지 않았으므로 dispatcher, redirect 두개의 포워딩 방식 모두 사용 가능, 현재는 dispatcher 방식으로 포워딩하자

- setPath() 메소드 안에는 WebContent 폴더를 기준으로 하위 폴더를 쓰면서 포워딩할 파일명을 적어주기

- 회원가입이 끝나면 loginform 으로 갈 것이므로 loginform.jsp 로 포워딩하자

 

- 그 후 객체 forward 를 리턴하면서 Controller 클래스의 이곳으로 간다

- MemberController.java 부분

- 요청을 받을때는 forward == null 이므로 만족하지 않았던 포워딩 처리의 조건문

- 이번엔 객체를 돌려받으므로 forward !=null 이 되어 포워딩 처리함

5. 이후 DAO 클래스를 작성 해야함

 

콘솔창 확인

- memberform.jsp 에서 '회원가입' 클릭시

- 여태까지 회원가입 폼 -> Controller 클래스  -> MemberInsert Service 클래스까지 넘어왔음을 알 수 있음

 

- 다음으로 DAO 클래스에서 insert() 메소드를 작성하자

- DAO 클래스의 코드는 Model 1 와 거의 같다

 

DAO 클래스 회원가입 기능 메소드 작성

- MemberDAO.java 전체 코드는 모두 구현 후 올리기

- MemberDAO.java 추가된 insert() 부분 코드만

	// 회원가입
	public int insert(MemberDTO member) {
		int result = 0;
		Connection con = null;
		PreparedStatement pstmt = null;
		try {
			con = getConnection();
			
			String sql = "insert into member2 ";
			sql += "values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getMailid());
			pstmt.setString(7, member.getDomain());
			pstmt.setString(8, member.getTel1());
			pstmt.setString(9, member.getTel2());
			pstmt.setString(10, member.getTel3());
			pstmt.setString(11, member.getPhone1());
			pstmt.setString(12, member.getPhone2());
			pstmt.setString(13, member.getPhone3());
			pstmt.setString(14, member.getPost());
			pstmt.setString(15, member.getAddress());
			pstmt.setString(16, member.getGender());
			pstmt.setString(17, member.getHobby());
			pstmt.setString(18, member.getIntro());

			result = pstmt.executeUpdate(); // SQL문 실행
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}
		}
		return result;
	}

- Model 1 에서 DAO의 insert() 메소드를 작성했던 것과 같은 방식으로 작성하면 된다

- Model1 DAO 회원가입 insert() 메소드 설명 : https://laker99.tistory.com/114?category=1080281

 

다음 흐름

- DB 에 insert 수행 후 DAO -> Service 클래스(MemberInsert.java) 로 간다

- Service 클래스에서 forward 객체를 생성 후 어디로 포워딩 할지, 어떻게 포워딩 할지 값만 설정한 후 forward 객체 리턴

- Service 클래스의 execute() 메소드를 호출한 Controller 클래스로 돌아가서 실제 포워딩을 수행한다

- Controller 클래스의 이곳으로 다시 돌아간다

- Controller 클래의 객체 forward 가 execute() 에서 리턴으로 ActionForward 객체를 받았으므로 더이상 fowrad 는 null 이 아님

- 처음에는 null 이었기에 실행되지 않았던 포워딩 코드를 이제는 null 이 아니므로 실행함

- getPath() 로 포워딩할 페이지를 불러와서 dispatcher 방식 또는 redirect 방식으로 포워딩 하면 된다

- 여기서는 dispatcher 방식으로 포워딩 했다

 

실행 캡처

- 먼저 memberform.jsp 회원가입 폼에서 회원가입 시키자

- 회원가입을 하면 로그인 페이지로 포워딩 된다, dispacher 방식 포워딩이므로 URL 변화 없음

- sql 파일에서 DB insert 되었는지 확인

- 삽입되었음을 확인 가능

 

- 콘솔창 보기

- Controller 클래스("post" 출력) -> Service 클래스("MemberInsert" 출력) -> DAO 클래스에서 DB에 삽입 -> Service 클래스("회원가입 성공" 출력) -> Controller 클래스 -> loginform.jsp 포워딩 을 콘솔창에서 찍혀진 결과로 확인 가능

 

회원관리 프로그램 : ID 중복검사

- memberform.jsp 파일을 보면

- 비동기적으로 입력창 아래에 사용 가능한 ID 메세지 띄우기

- Ajax는 만들어져 있으므로 저렇게 글자는 뜬다

- 해당 서비스 클래스를 만들어야 실제로 ID중복검사를 하고, 제대로 동작한다

 

- 이제 member.js 파일에서 Ajax 로 비동기적으로 서버창에 요청하는 코드를 보자

- Idcheck.do 로 요청한다, Controller 클래스로 찾아가서 doPost() 가 실행됨, 이때 URL 에는 /Idcheck.do 가 찍힌다

- 'ID중복검사' 버튼 클릭시 요청 이름값인 Idcheck.do 가 콘솔창에 나온다

- 요청을 했고 그 요청이 Controller 클래스까지 갔다는 의미이다

 

- 이제 요청을 실제로 처리하는 Service 클래스를 만들어야한다

 

회원관리 프로그램 : ID중복검사 Service 클래스

- 실제 ID중복검사 요청을 처리하는 Idcheck.java 파일을 만들자

- 회원가입 폼의 요청이름값과 동일하게 설정

- service 패키지에 IdCheck.java 클래스 생성

- IdCheck.java

package service;

import java.io.PrintWriter;

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

import dao.MemberDAO;

public class IdCheck implements Action{

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("IdCheck");
		
		// 출력 스트림 객체 생성
		PrintWriter out = response.getWriter();
		
		String id = request.getParameter("id");
		System.out.println("id:" + id);
		
		MemberDAO dao = MemberDAO.getInstance();
		int result = dao.idcheck();	// ID중복검사
		System.out.println("result:" + result); // 1 : 중복 ID //-1 : 사용 가능한 ID
		
		// 웹브라우저에 출력되는 값이 callback 함수로 리턴됨
		out.println(result);
		
		return null;
	}

}

* 아래의 Controller 클래스에서 이 Service 클래스로 가는 코드를 먼저 작성 한 후 다시 이 코드로 돌아와 작성했다

- 먼저 Action 인터페이스를 상속하고 execute() 메소드 오버라이딩

- 지금은 비동기로 처리하므로 Controller 클래스로 돌아가지 않는다! 그래서 return null을 함

- 돌아갈때 member.js 로 돌아가야한다, 이때 브라우저에 출력되는 값이 callback 함수로 리턴되므로 1 또는 -1 이 돌아감

- member.js 에서 요청되면서 넘어온 값을 request.getParamter("id") 로 받는다

- DAO 객체 생성해서 메소드 idcheck() 호출하며 사용자의 id 를 넘기기, 중복이면 1 리턴, 사용가능한 아이디면 -1 리턴

- 브라우저에 출력되는 값이 콜백함수로 리턴되므로, 이 IdCheck.java 에서 출력해야함, 출력위해 out 객체 생성

- out 객체로 DAO 의 idcheck() 에서 돌려받은 값 result 를 출력, 그럼 member.js 에서 data 로 돌려받음

+ Model 2 에선 JSP 의 내장객체 없다, request, response 만 받아서 사용 가능하고 나머지 객체는 직접 만들어야함

 

- 다음은 다시 Controller 클래스로 돌아가서 ID중복검사에서 요청이 올경우 IdCheck.java Service 클래스로 보내주는 코드 작성

 

Controller 클래스에서 ID 중복검사 Service 클래스로 가기

- MemberController.java 전체 코드는 나중에

- MemberController.java 부분

		// ID중복 검사 (ajax)
		} else if (command.equals("/Idcheck.do")) {
			try {
				action = new IdCheck();
				forward = action.execute(request, response);
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}

- IdCheck() 클래스로 객체 생성하고, 그 객체에서 execute() 실행하기

- 이 코드 작성 후 회원가입 폼에서 'ID중복검사' 버튼 클릭시 콘솔창 확인하면

- IdCheck 가 찍히는 걸 보아, 요청하는 곳 -> Controller -> Service 클래스까지 잘 도착했음을 확인 가능

- id: lay99 이 찍히는 걸 보아, Ajax로 요청하면서 넘어온 값이 Service 클래스에서 잘 받았음을 확인 가능

 

- 이제 DAO 클래스에 ID중복검사를 하기 위한 메소드 idcheck() 작성하기

 

DAO 클래스 ID중복검사 메소드 작성

- MemberDAO.java 전체 코드는 모두 구현 후 올리기

- MemberDAO.java 추가된 idchcek() 부분 코드만

- MemberDAO.java (추가)

	// ID중복 검사 (ajax)
	public int idcheck(String id) {
		int result = 0;
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = getConnection();
			
			String sql = "select * from member2 where id = ?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {
				result = 1;	// 중복 ID
			} else {
				result = -1; // 사용 가능한 ID
			}
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try { rs.close(); } catch(Exception e) {}
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}
		}
		return result;
	}

- select 문이므로 ResultSet 객체도 생성

- select SQL문 실행 후 rs.next 가 true 인 경우엔 DB 에 중복아이디가 있다는 의미이다

- 중복 ID 면 1 을 리턴, 사용 가능한 ID 면 -1 을 Service 클래스 IdCheck.java 로 돌아가며 리턴

 

- memberform.jsp 를 실행해서 ID중복검사 를 해보자

- 이미 가입된 ID 입력시

- 콘솔창 확인

- Service 클래스에서 DAO 로 부터 받은 값을 Service 클래스에서 result 로 받아 출력하고 있다, 중복 ID 이므로 1 이 출력

 

- 가입되지 않은 ID 입력시

- 콘솔창 확인

- Service 클래스에서 DAO 로 부터 받은 값을 Service 클래스에서 result 로 받아 출력하고 있다, 사용 가능한 ID 이므로 -1 이 출력


회원관리 프로그램 : 로그인 기능

- 이제 로그인 기능을 구현하자

- 먼저 로그인 폼인 loginform.jsp 파일을 보자

- loginform.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
	<!DOCTYPE html>
	<html>
	<head>
	<meta charset="UTF-8">
	<title>로그인 폼</title>
	<script src="http://code.jquery.com/jquery-latest.js"></script>
	
	<!-- 외부 자바스크립트 파일 불러오기 -->
	<script src="<%=request.getContextPath() %>/member/login.js"></script>
	
	</head>
	<body>
	
	<form method="post" action="<%=request.getContextPath() %>/Login.do">
	<table border=1 width=350 align=center>
		<caption>로그인</caption>
		<tr>
			<td>ID</td>	
			<td><input type=text size=30 id="id" name="id" autofocus="autofocus"></td>	
		</tr>
		<tr>
			<td>비밀번호</td>
			<td><input type="password" size=30 id="passwd" name="passwd"></td>
		</tr>
		<tr>
			<td colspan=2 align=center>
				<input type="button" value="회원가입" 
				       onClick="location.href='<%=request.getContextPath()%>/MemberForm.do' ">
				<input type="submit" value="로그인">
				<input type="reset" value="취소">
			</td>
		</tr>
		
	</table>
	</form>
	
	
	</body>
	</html>

- 외부 자바스크립트 파일을 불러올때 request.getContext() 로 프로젝트명을 구하고. WebContent 기준 하위 폴더와 파일명 적기

+ '로그인' 버튼만 submit 버튼으로서 클릭시 입력된 값을 post 방식으로 전송, Controller 클래스로 간다

 

'회원가입' 으로 넘어갈때 주의

- '회원가입' 을 클릭시 바로 memberform.jsp 로 가는 것이 아님

- Model 2 이기 때문에 Controller 클래스를 갔다가 다시 가입 폼 (View)으로 가야함

- '회원가입' 클릭시 Controller 클래스로 먼저 가기 위해 memberform.jsp 대신 MemberForm.do 로 do 확장자로 요청해서 어노테이션으로 Controller 클래스로 찾아가게함

- Controller 클래스의 doGet() 메소드가 실행됨

- 로그인폼에서 '회원가입' 클릭시 콘솔창

- Controller 클래스로 간것을 확인 가능, 요청 이름값은 MemberForm.do

 

- Controller 클래스에서 MemberForm.do 로 요청이 올때 어떻게 처리할지를 작성해야한다

 

Controller 클래스에서 회원가입 폼으로 가기

- MemberController.java 전체 코드는 나중에

- MemberController.java 부분

- MemberForm.do 로 요청이 올때의 경우를 처리

		// 회원가입 폼
		} else if (command.equals("/MemberForm.do")){
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("./member/memberform.jsp");
		}

- DB 연동을 하는 경우가 아니므로 Service 클래스로 가지 않고 바로 회원가입 폼으로 가면 된다

- 바로 forward 객체를 생성하고 setRedirect(), setPath() 로 값을 설정해줌, 원래 이 작업은 Service 클래스 하단에서 해주는 거지만 여기선 Service 클래스로 가지 않으므로 여기서 값 설정

- 여기서 forward 객체는 null 이 아니게 되므로 아래의 코드인 포워딩 코드에서 포워딩되어 회원가입폼으로 간다

+ 모두 Service 클래스로 가는 것이 아님, DB연동 없으면 Service 클래스로 넘어가지 않는다

 

- 지금까지 로그인 폼에서 '회원가입' 클릭시 회원가입 폼으로 넘어가도록 처리함

- 이제 진짜 로그인 기능을 구현하자

- loginform.jsp 에서 아이디, 비밀번호 입력 후 '로그인' 클릭 시 콘솔창

- Controller 클래스가서 doPost() 를 실행했음을 알 수 있다.

 

앞으로 해야할 일

1. Service 클래스 명도 맞추서 Login.java 파일로 하자

2. Controller 클래스에서 "/Login.do" 인 경우를 Login.java 로 보내는 것을 처리하자

3. Service 와 DAO 부분 구현

 

- 로그인 기능 Service 클래스인 Login.java 파일 생성부터 하자

 

회원관리 프로그램 : 로그인 Service 클래스

- 실제 로그인 요청을 처리하는 Login.java 파일을 만들자

- 로그인 폼의 요청이름값과 동일하게 설정

- service 패키지에 Login.java 클래스 생성

- Login.java (수정 전, 한글 인코딩 전, 한글 인코딩 빼고는 다 작성함)

package service;

import java.io.PrintWriter;

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

import dao.MemberDAO;

public class Login implements Action{

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Login");
		
		request.setCharacterEncoding("utf-8");
		
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		
		String id = request.getParameter("id");
		String passwd = request.getParameter("passwd");
		
		MemberDAO dao = MemberDAO.getInstance();
		int result = dao.memberAuth(id, passwd); // 회원인증
		if(result == 1) System.out.println("회원인증 성공");
		
		if(result == 1) {	// 회원인증 성공
			session.setAttribute("id", id);
		} else {	// 회원인증 실패
			out.println("<script>");
			out.println("alert('로그인 실패');");
			out.println("history.go(-1);");
			out.println("</script>");
			out.close();
			
			return null;
		}
		ActionForward forward = new ActionForward();
		forward.setRedirect(false); // dispatcher 방식으로 포워딩
		forward.setPath("./member/main.jsp");
		
		return forward;
	}

}

<로그인 Service 클래스 형식, 전체적인 흐름>

- 부모 인터페이스인 Action 인터페이스를 상속받기, 이클립스 자동 기능으로 execute() 를 메소드 오버라이딩 하기

- request 객체는 Controller 클래스의 getPost() -> getProcess() -> Service 클래스의 execute() 로 넘어왔다

- 매개변수를 통해 Controller 클래스의 request 객체가 그대로 넘어왔으므로, 폼에서 Controller 클래스로 넘겨준 form 의 각종 입력양식의 값들을 여기 Service 클래스에서 request.getParamter() 로 가져올 수 있다

- 필드값을 설정한 ActionForward 객체를 execute() 를 호출한 Controller 클래스에 돌려줌

 

<로그인 Service 클래스 작성 순서>

1. 먼저 post 방식으로 한글값이 넘어올 수 있으므로 한글값 인코딩을 설정한다

2. 회원 인증 성공시 공유설정을 해야하므로 session 객체 생성, out 객체도 생성해주자

3. 로그인 폼에서 전달한 id, passwd 를 받아온다

- 다음으로는 이 id, passwd 와 DB의 id, passwd 가 같으면 공유설정해야함

4. DAO 객체를 생성하고 회원 인증 select 를 하는 DAO 의 memberAuth() 메소드 호출

- 매개변수로는 id, passwd 를 전달

- 회원 인증에 성공시 결과값을 1로 받기로 하자

5. 회원 인증 성공시 "id" 를 네임값으로 회원의 id 를 공유 설정을 한다

- 파일을 계속 넘어가도 session 값은 유지됨

6. 회원 인증 실패시 out 객체를 통해 실패 메세지를 뿌린다

- 실패시 알림창을 띄우고 이전 페이지로 돌아간다

- return null 이 없으면 콘솔창에 에러가 뜬다, return null 을 통해 이 메소드를 완전히 빠져나가며 아래 내용 실행 안함

- out 객체를 닫아줌

- 회원 인증 성공시, return null 로 빠져나가지 않고 아래 코드가 실행됨

7. 회원 인증 성공시 Service -> 다시 execute() 를 호출한 Controller 로 돌아가야한다

- 이때 Controller 로 ActionForward 객체를 리턴해야한다, ActionForward 객체 forward 생성

- 리턴하기 전에 어떤 방식으로 포워딩할지, 어느 파일로 포워딩할지를 setRedirect(), setPath() 로 설정

- 지금은 request 객체로 공유를 설정하지 않았으므로 dispatcher, redirect 두개의 포워딩 방식 모두 사용 가능, 현재는 dispatcher 방식으로 포워딩하자

- setPath() 메소드 안에는 WebContent 폴더를 기준으로 하위 폴더를 쓰면서 포워딩할 파일명을 적어주기

- 회원가입이 끝나면 main 페이지로 갈 것이므로 main.jsp 로 포워딩하자

8. 이후 DAO 클래스를 작성 해야함

 

+ out 객체와 session 객체 만들기

		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();

- DAO 클래스로 가서 회원 인증 (로그인) 을 해주는 memberAuth() 메소드를 작성하자

 

DAO 클래스 회원인증 (로그인) 기능 메소드 작성

- MemberDAO.java 전체 코드는 모두 구현 후 올리기

- MemberDAO.java 추가된 memberAuth() 부분 코드만

	// 로그인 (회원인증)
	public int memberAuth(String id, String passwd) {
		int result = 0;
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = getConnection();
			
			String sql = "select * from member2 where id = ? and passwd=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			pstmt.setString(2, passwd);
			rs = pstmt.executeQuery();	//SQL문 실행
			
			if(rs.next()) {	// 회원인증 성공
				result = 1;
			} else {		// 회원인증 실패
				result = -1;
			}
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try { rs.close(); } catch(Exception e) {}
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}
		}
	return result;
	}

- select * from member2 where id =? and passwd = ? 에서 결과를 가져온다는 것은 아이디, 비번이 모두 일치하는 결과가 있다는 의미

- 회원 인증 성공시 1 리턴, 실패시 -1 리턴

- 이후 이 메소드를 호출한 Service 클래스로 이동 -> Controller 클래스로 이동 -> main.jsp 로 포워딩하게 된다

- Service 클래스 -> Controller 클래스로 갈때 forward 객체를 리턴했음

- Controller 클래스에서 main.jsp 로 포워딩 한다

 

- 아직 Controller 클래스에서 "/Login.do" 가 요청이름값일때의 Login.java 로 보내는 처리를 하지 않았음

- Controller 클래스에서 Service 클래스로 연결하는 것은 

 

Controller 클래스에서 로그인 Service 클래스로 가기

- MemberController.java 전체 코드는 나중에

- MemberController.java 부분

- Login.do 로 요청이 올때의 경우를 처리

		// 로그인 (회원 인증)
		} else if(command.equals("/Login.do")) {
			try {
				action = new Login();
				forward = action.execute(request, response);
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}

 

- 이제 모든게 연결되었으므로 loginform.jsp 에서 로그인을 시도해보자

- 맞는 비밀번호 입력시

- 아직 main.jsp 가 만들어지지 않았으므로 오류 발생

- 콘솔창을 보면 로그인 폼 -> Controller 클래스("post" 출력) -> Service 클래스("Login" 출력) -> DAO 에서 DB 연결 -> Service 클래스("회원가입 성공" 출력) -> Controller 클래스 -> main.jsp 로 포워딩 잘 되었음을 확인 가능

- 틀린 비밀번호 입력시

- 로그인 실패 라는 메세지 대신 깨진 한글값이 나온다

 

깨진 한글값 문제 처리

- Login.java 파일에서 회원가입 실패시 출력하는 메세지가 한글이 깨져서 나타난다

- 위에서 "한글값" 을 인코딩하는 setCharacterEncoding("utf-8") 은 있지만 현재 문서의 한글 인코딩은 안했다

- 그래서 alert 로 출력되는 한글이 깨졌던 것

- JSP 에서는 자동으로 생성되었던 현재 문서의 한글을 인코딩하는 코드

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

- 이 코드를 JSP 가 아니라 Java 클래스 내에서 JAVA 에 맞게 작성해야함

		response.setContentType("text/html; charset=utf-8");

- 이 한줄을 Login.java 에 추가해야함

 

+ 이 코드는 한글값 인코딩, 한글 문서 인코딩과 관련없다

		request.setCharacterEncoding("utf-8");

 

- Login.java (수정 후, 한글 인코딩 완료)

package service;

import java.io.PrintWriter;

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

import dao.MemberDAO;

public class Login implements Action{

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Login");
		
		response.setContentType("text/html; charset=utf-8");
		request.setCharacterEncoding("utf-8");
		
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		
		String id = request.getParameter("id");
		String passwd = request.getParameter("passwd");
		
		MemberDAO dao = MemberDAO.getInstance();
		int result = dao.memberAuth(id, passwd); // 회원인증
		if(result == 1) System.out.println("회원인증 성공");
		
		if(result == 1) {	// 회원인증 성공
			session.setAttribute("id", id);
		} else {	// 회원인증 실패
			out.println("<script>");
			out.println("alert('로그인 실패');");
			out.println("history.go(-1);");
			out.println("</script>");
			out.close();
			
			return null;
		}
		ActionForward forward = new ActionForward();
		forward.setRedirect(false); // dispatcher 방식으로 포워딩
		forward.setPath("./member/main.jsp");
		
		return forward;
	}
}

 

- 다시 loginform.jsp 를 실행하고 틀린 아이디나 비밀번호를 입력 후 '로그인' 을 클릭하자

- 문서의 한글 인코딩이 잘 처리 되었다!

 

- 맞는 비밀번호를 입력했을때도 한글이 깨지는 문제 해결됨

- main.jsp 파일이 아직 생성되지 않아서 아직 404 에러가 뜬다

 

중간 정리

+ 현재 공유된 값 : 로그인 성공시 session 으로 공유된 id 값

- 그래도 main.jsp 로 포워딩하는 것까지 Controller 클래스에서 다 처리했다

- Service 클래스를 거쳐서 돌아올때는 forward 객체가 null 이 아니므로 조건식을 만족해서 포워딩함

- session 으로 공유를 설정할때는 어느 방식으로 포워딩해도 상관없다

- 지금 로그인 페이지는 session 으로만 공유설정했으므로 상관없음, 나중에 request 객체로 공유 설정시에는 Dispatcher 방식으로 포워딩 해야함

 

- main.jsp 파일에서는 세션 유무에 따라 보이는 화면이 달라진다


회원관리 프로그램 : 중간 페이지 main.jsp

세션 유무(로그인 성공 유무) 에 따라 다른 화면 보여주기

- WebContent/member 폴더 하위에 main.jsp 파일 생성 및 작성

- main.jsp (수정 전 1)

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

<!-- 세션이 있는 경우 -->
<c:if test="${sessionScope.id != null }">
	${sessionScope.id} 님 환영 합니다. <br><br>
	
	회원정보 수정 <br>
	로그아웃 <br>
	회원탈퇴 <br>
</c:if>
<!-- 세션이 없는 경우 -->
<c:if test="${sessionScope.id == null}">
	회원가입 <br>
	로그인 <br>
</c:if>

- EL / JSTL 사용하기

- JSTL 코어 라이브러리를 불러온다

- main.jsp 파일에서는 세션 유무에 따라 보이는 화면이 달라진다

- session 값이 있는경우, 없는 경우 두가지 경우로 나눠서 처리, JSTL 의 if 태그 사용

- 조건식은 EL 로 만들고 sessionScope 내장객체를 사용함, sessionScope.id 는 session 으로 공유된 네임 "id" 의 값 의미

 

- 세션 값이 있을때 (즉, 로그인 (회원인증) 하고 main.jsp 로 왔을때)

- 세션 값이 없을때 (바로 main.jsp 를 그냥 실행했을때)

 

- 이제 세션이 없는 경우 나타나는 텍스트인 '회원가입' 과 '로그인' 에 링크걸기

- main.jsp (수정 전 2)

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

<!-- 세션이 있는 경우 -->
<c:if test="${sessionScope.id != null }">
	${sessionScope.id} 님 환영 합니다. <br><br>
	
	회원정보 수정 <br>
	로그아웃 <br>
	회원탈퇴 <br>
</c:if>
<!-- 세션이 없는 경우 -->
<c:if test="${sessionScope.id == null}">
	<a href="<%=request.getContextPath() %>/MemberForm.do">회원가입 </a> <br>
	<a href="<%=request.getContextPath() %>/LoginForm.do">로그인 </a> <br>
</c:if>

<회원가입 링크>

- href = "./MemberForm.do" 만을 설정시 못 찾아간다

- 앞에 프로젝트 명을 붙여서 이동시켜줘야함

- 콘솔창

<로그인 링크>

- 아직 Controller 클래스에 로그인 폼으로 넘겨주는 코드는 없다

- 요청이름값을 "LoginForm.do" 로 하자

- LoginForm.do 로 요청 했으므로 Controller 클래스로 찾아가긴 했다

- 마찬가지로 프로젝트 명을 앞에 써주기 위해 request.getContextPath() 사용

- Controller 클래스에서 /LoginForm.do 로 올때를 처리해주기

- 폼이 아니므로 무조건 Get 방식으로 전달한다,

- 콘솔창

- command 변수에 요청 이름값이 저장되어있다

- Controller 클래스에서 command 가 LoginForm.do 일때 로그인 폼으로 가는 코드를 작성

 

Controller 클래스에서 로그인 폼으로 가기

- MemberController.java 전체 코드는 나중에

- MemberController.java 부분

- LoginForm.do 로 요청이 올때의 경우를 처리

		// 로그인 폼	
		} else if(command.equals("/LoginForm.do")) {
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("./member/loginform.jsp");
		}

- 지금은 DB연동을 안하므로 Service 클래스로 갈 필요 없다

- 회원가입 폼으로 가는 것과 마찬가지로 처리한다

- ActionForward 객체 forward 를 생성후 바로 값을 세팅해줌

- View 페이지는 member 폴더 하위 loginform.jsp 이다

- dispatcher 방식으로 포워딩 한다

 

- 그 후에 아래의 포워딩 코드에서 forward != null 을 만족하므로 포워딩한다

 

- main.jsp 실행 후 '로그인' 누르기

+ 세션값이 없으므로 아래 화면이 뜬다

- 로그인 포믕로 잘 이동했음을 확인 가능

 

Model 1 vs Model 2

- Model 1 에서는 Loginform.jsp 로 바로 갈 수 있다

- Model 2 에서는 Controller 로 갔다가 다시 View (Loginform.jsp) 로 가도록 설정해야한다

 

- 다시 main.jsp 를 보자

- sessionScope.id 는 EL 내장객체, session.getAttribute("id") 를 대신한다

- sessionScope.id 대신 다른 방법이 있다, empty 연산자

- 위의 if 조건식을 empty 연산자로 바꿔서 처리해보자

 

empty 연산자

- '비어있는지', '없는지' 를 묻는 EL연산자

- 비어있으면 true, 비어있지 않으면 false 값이 된다

 

empty 연산자 코드로 바꾸기 1

- main.jsp 의 '세션이 있는 경우' if 태그 코드를 empty 연산자 코드로 바꾸기

<!-- 세션이 있는 경우 -->
<c:if test="${sessionScope.id != null }">

- 아래 코드로 바꿀 수 있다

<!-- 세션이 있는 경우 -->
<c:if test="${!empty sessionScope.id }">

- empty 연산자는 없으면 true 이므로 세션이 있는 경우는 ! 를 앞에 붙여야함

- empty 연산자는 == null 과 같은 의미, '없으면' 의 의미이다

 

empty 연산자 코드로 바꾸기2

- 마찬가지로 main.jsp 의 '세션이 없는 경우' if 태그 아래 코드는 이렇게 바꾼다

<!-- 세션이 없는 경우 -->
<c:if test="${sessionScope.id == null}">

- 아래코드로 바꾼다

<!-- 세션이 없는 경우 -->
<c:if test="${empty sessionScope.id }">

- 또한 이렇게 sessionScope 를 빼고 id 만 적어도 똑같이 처리된다

<!-- 세션이 없는 경우 -->
<c:if test="${empty id }">

- 똑같이 처리된다

- sessionScope 를 적는게 원칙이지만 빼도 처리된다

 

- main.jsp (수정 전 3)

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

<!-- 세션이 있는 경우 -->
<c:if test="${!empty sessionScope.id }">
<%-- <c:if test="${sessionScope.id != null }"> --%>
	${sessionScope.id} 님 환영 합니다. <br><br>
	
	회원정보 수정 <br>
	로그아웃 <br>
	회원탈퇴 <br>
</c:if>
<!-- 세션이 없는 경우 -->
<c:if test="${empty sessionScope.id }">
<%-- <c:if test="${sessionScope.id == null}"> --%>
	<a href="<%=request.getContextPath() %>/MemberForm.do">회원가입 </a> <br>
	<a href="<%=request.getContextPath() %>/LoginForm.do">로그인 </a> <br>
</c:if>

회원관리 프로그램 : 로그아웃

- main.jsp 세션있는 경우에서 나타나는 차에서 '로그아웃' 을 눌렀을때 로그아웃을 수행하는 기능을 만들자

 

- main.jsp 에서 링크를 연결하자

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

<!-- 세션이 있는 경우 -->
<c:if test="${!empty sessionScope.id }">
<%-- <c:if test="${sessionScope.id != null }"> --%>
	${sessionScope.id} 님 환영 합니다. <br><br>
	
	회원정보 수정 <br>
	<a href="./Logout.do">로그아웃</a> <br>
	회원탈퇴 <br>
</c:if>
<!-- 세션이 없는 경우 -->
<c:if test="${empty sessionScope.id }">
<%-- <c:if test="${sessionScope.id == null}"> --%>
	<a href="<%=request.getContextPath() %>/MemberForm.do">회원가입 </a> <br>
	<a href="<%=request.getContextPath() %>/LoginForm.do">로그인 </a> <br>
</c:if>

- 수정한 부분 코드만 캡처

- 요청 이름값은 "/Logout.do" 로 하자

- 로그아웃 처리는 DB연동을 안하므로 Service 클래스로 갈 필요 없음

- 로그인 하고 main.jsp 로 와서 '로그아웃' 을 눌러보자

- command 에 요청 이름값 "/Logout.do" 이 출력되고 있다

- Controller 클래스의 doGet(), doProcess() 메소드 안까지 잘 찾아 간 것

 

- Controller 클래스로 가서 요청이 "/Logout.do" 로 온 경우에 View 페이지로 넘겨주는 처리를 하자

 

Controller 클래스에서 회원가입 폼으로 가기

- MemberController.java 전체 코드는 나중에

- MemberController.java 부분

- Logout.do 로 요청이 올때의 경우를 처리

		// 로그아웃
		} else if(command.equals("/Logout.do")) {
			forward = new ActionForward();
			forward.setRedirect(false);
			forward.setPath("./member/logout.jsp");
		}

- 지금은 DB연동 안하므로 Service 클래스 갈 필요 없다

- 로그아웃 View 페이지인 logout.jsp 로 보내주기만 하면 된다.

- 그래서 회원가입 폼으로 갈 때와 비슷하게 처리한다

- ActionForward 객체 forward 를 생성하고 바로 값을 설정함

 

- 이제 member 폴더 하위에 logout.jsp 파일을 생성하자

- logout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
	// 세션 삭제
	session.invalidate();
%>

<script>
	alert("로그 아웃");
	location.href="./LoginForm.do"
</script>

logout.jsp 에서 해야할 일

1. session 삭제

- 브라우저 창이 닫히지 않아도 강제로 session 끊기

- session.invalidate() 메소드 사용

2. 로그아웃 되었다는 메세지를 뿌린 후 다시 로그인 폼으로 가기(포워딩)

- 로그인 폼으로 가는 요청이름인 "/LoginForm" 을 사용해서 로그인 폼으로 간다

 

- 로그인 폼에서 로그인 한 후 main.jsp 에서 '로그아웃' 클릭하자

- 로그인 폼으로 잘 넘어간다.

- Controller 클래스에서 View 페이지로 포워딩되었다

+ 그 상태에서 main.jsp 실행시 이 화면이 뜨는걸 보아 세션이 삭제되었다

- 콘솔창

- 로그아웃 기능 구현 완료

 

다음에 만들 Model 2 게시판 프로그램

- 이후에 만들 프로그램

- request 객체로 공유를 많이 한다

- lib 폴더에 라이브러리를 저장하는 대신 maven 을 사용한다

+ Recent posts