JSP & Servlet

DAY 52 - MVC ( 2024.09.13 )

summ.n 2024. 9. 13. 17:38

1. init 메서드 실행

@Override
public void init(ServletConfig config) throws ServletException {
    String propertyConfig = config.getInitParameter("propertyConfig");
    System.out.println("propertyConfig = " + propertyConfig);

 

  • propertyConfig는 서블릿의 초기화 파라미터인 "command.properties"의 파일 이름을 가져온다.
  • config.getInitParameter("propertyConfig")로 가져온 이 값은 나중에 프로퍼티 파일을 로드할 때 사용된다.

propertyConfig = command.properties

 

 

2. 프로퍼티 파일의 실제 경로 설정

서블릿에서 설정한 초기화 파라미터에 해당하는 파일을 찾기 위해 해당 파일의 실제 경로를 설정다.

// 서블릿이 실행되는 웹 애플리케이션의 실제 경로
String realFolder = config.getServletContext().getRealPath("/WEB-INF");
String realPath = realFolder + "/" + propertyConfig;
System.out.println("realPath = " + realPath);

 

  • getRealPath("/WEB-INF")는 애플리케이션 내에서 WEB-INF 폴더의 실제 경로를 가져온다.
  • realPath는 이 경로에 command.properties 파일 이름을 붙여 프로퍼티 파일의 실제 위치를 나타낸다.

realPath = D:\Web\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\memberMVC\WEB-INF/command.properties

 

 

3. 프로퍼티 파일 로드 및 파싱

FileInputStream fin = null;
Properties properties = new Properties();

try {
    fin = new FileInputStream(realPath);
    properties.load(fin);
    System.out.println("properties = "+properties);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        fin.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

 

  • FileInputStream으로 realPath 경로에 있는 command.properties 파일을 읽어온다.
  • properties.load(fin)은 이 파일의 내용을 읽어서 properties 객체에 저장한다.
  • properties 객체는 키-값 쌍으로 구성된다.

 

properties = {/member/writeForm.do=member.service.WriteFormService,           

                    /member/loginForm.do=member.service.LoginFormService,   

                    /member/checkId.do=member.service.CheckIdService}

 

컬렉션

1. Collection => 순서, 중복

2. Set            => 순서x, 중복x

3. Map <Key,Value>

 

 

4. 프로퍼티 파일의 각 키-값 쌍을 이용해 클래스 인스턴스화

Iterator<Object> it = properties.keySet().iterator();

 

  • properties.keySet()은 프로퍼티 파일의 모든 키를 가져온다.
  • properties에 똑같은 내용이 들어가면 set으로 바꾸겠다라는 의미 !

 

 

command.properties

#요청=클래스명
/member/writeForm.do=member.service.WriteFormService
/member/writeForm.do=member.service.WriteFormService
/member/writeForm.do=member.service.WriteFormService
/member/writeForm.do=member.service.WriteFormService
/member/loginForm.do=member.service.LoginFormService
/member/checkId.do=member.service.CheckIdService

 

똑같은 내용을 이렇게나 많이 넣어도 똑같이 출력되는 것을 확인할 수 있다.

 

properties = {/member/writeForm.do=member.service.WriteFormService,           

                    /member/loginForm.do=member.service.LoginFormService,   

                    /member/checkId.do=member.service.CheckIdService}


똑같은 내용이 여러개 들어가버리면

set형식으로 바꿔버린다. set은 중복을 허용안하기 때문에 위에처럼 뜨는 것 !!

 

그리고 접근지정자 iterator를 만들어놓고 내가 하나하나의 요청과 클래스에 접근할 수 있는 것이다.


String    "String" 차이점은?

String - 문자열을 처리할 수 있는 자료형

"String" - 그냥 글자라는 것

 

 

key:  /member/writeForm.do

className: " member.service.WriteFormService"  ----- 그냥 글씨이다. new할 수 없다.

이걸 new로 하려면 자료형으로 바꿔야한다.

하지만 얘네는 그냥 글씨이다. 우리가 원하는 건 객체형이라는 것 !!!

 

key:  /member/ loginForm.do

className: "member.service. LoginFormService "

또 로그인할 때는 이 부분이므로 자료형이 계속해서 달라진다.


 Class<?> classType = Class.forName(className);

 

 

그러므로 일단 자바의 클래스타입으로 몰아붙이는 것이다. (드라이버 로딩할 때도 써먹음)

일단 모르면 클래스타입으로 하고 Object로 생성해버리는 것


Object ob = classType.getConstructor().newInstance();

 

메모리에 new해서 클래스를 생성했기 때문에 갖다쓸 수 있는 것이다.

 

ob = member.service.WriteFormService@2a991776 --- 이렇게 객체가 되는 것이다.

 

category = /member/checkId.do

그래서 이렇게 요청이 들어오면 우리가 할 수 있는 것이다.

 

map.put(key, ob);
  • 만들어진 인스턴스는 map.put(key, ob)를 통해 map에 저장된다. key는 요청 URL 패턴이고, ob는 그 요청을 처리할 서비스 객체이다.

 


로그인

 

memberLoginForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 페이지</title>
<style type="text/css">
body {
    background-color: #FFE2FA;
    font-family: 'Arial', sans-serif;
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 50vh;
    flex-direction: column;
}

table {
   width: 500px;
   margin: auto;
   background-color: white;
   border-radius: 10px;
   padding: 20px;
}

th {
   padding: 10px 15px;
   text-align: left;
   color: #333;
   font-size: 16px;
}

td {
   padding: 10px 10px;   
}

div {
   color: red;
   font-size: 10pt;
   font-weight: bold;
   margin-top: 5px;
}

input[type="text"], input[type="password"] {
   width: 100%;
   padding: 8px;
   border: 1px solid #CCC;
   border-radius: 5px;
}

input[type="button"], input[type="submit"] {
   background-color: #FF9ADB; 
   border: none;
   font-size: 16px; 
   padding: 10px 15px;
   border-radius: 5px;
   cursor: pointer;
   color: white;
   transition: background-color 0.3s ease;
}

input[type="button"]:hover, input[type="submit"]:hover {
   background-color: #FF70C0;
}

img {
   margin: 20px 0;
   cursor: pointer;
}


</style>
</head>
<body>
<img src="../image/free-icon-love-4096198.png" alt="홈" width="60" height="60" onclick="location.href='../index.jsp'" />
   <form id="loginForm">
      <table>
         <tr>
            <th>아이디</th>
            <td>
               <input type="text" name="id" id="id" placeholder="아이디 입력" />
               <div id="idDiv"></div>
            </td>
         </tr>
         <tr>
            <th>비밀번호</th>
            <td>
               <input type="password" name="pwd" id="pwd" placeholder="비밀번호 입력" />
               <div id="pwdDiv"></div>
            </td>
         </tr>
         <tr>
             <td colspan="2" align="center">
                 <input type="submit" value="로그인" id="loginBtn"/>
                 <input type="button" value="회원가입" onclick="location.href='memberWriteForm.jsp'" />
             </td>
         </tr>
      </table>
      <!--  쿠키 = <span></span> -->
   </form>

 

 

url: '/memberMVC/member/login.do' ------ 이제는 jsp로 보내는 것이 아닌 거 확인 !!

 

<script src="../js/member.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-3.7.1.min.js"></script>
<script type="text/javascript">
$('#loginBtn').click(function(event) {
    event.preventDefault(); // 기본 제출 동작 방지
    
    $('#idDiv').empty();
    $('#pwdDiv').empty();
    
    if ($('#id').val() == '') {
        $('#idDiv').html('아이디를 입력하세요.');
    } else if ($('#pwd').val() == '') {
        $('#pwdDiv').html('비밀번호를 입력하세요.');
    } else {
        $.ajax({
            type: 'POST',
            url: '/memberMVC/member/login.do',
            data: {
                'id': $('#id').val(),
                'pwd': $('#pwd').val()
            },
            dataType: 'text', // 서버로부터 순수한 텍스트만 받음
            success: function(data) {
               console.log(data);
                if (data.trim() === 'fail') {
                    alert("아이디 또는 비밀번호가 틀렸습니다.");
                } else {
                    alert(data.trim() + "님이 로그인하였습니다.");                    
                    location.href = '../index.jsp'
                }
            },
            error: function(e) {
                console.log(e);
            }
        });
    }
});

</script>

</body>
</html>

command.properties - /member/login.do 만들기

#요청=클래스명
#회원가입
/member/writeForm.do=member.service.WriteFormService
/member/checkId.do=member.service.CheckIdService

#로그인
/member/loginForm.do=member.service.LoginFormService
/member/login.do=member.service.LoginService

ControlServlet.java

초기화 (init 메서드)

ControlServlet의 init 메서드는 command.properties 파일을 읽어서 요청 경로와 처리 클래스를 매핑하는 Map을 초기화한다. 이 과정에서 /member/login.do 경로와 member.service.LoginService 클래스의 인스턴스도 Map에 저장된다.

// command.properties 파일에서 클래스 정보를 읽어 Map에 저장
FileInputStream fin = new FileInputStream(realPath);
Properties properties = new Properties();
properties.load(fin);

Iterator<Object> it = properties.keySet().iterator();
while (it.hasNext()) {
    String key = (String) it.next(); // 요청 경로
    String className = properties.getProperty(key); // 클래스 이름
    Class<?> classType = Class.forName(className);
    Object ob = classType.getConstructor().newInstance();
    map.put(key, ob); // Map에 저장
}

요청 처리 (execute 메서드)

클라이언트가 /member/login.do URL로 요청을 보내면 doGet 또는 doPost 메서드가 호출되고,

이 메서드는 execute 메서드를 호출한다.

 

  • 요청 url 경로 추출
String category = request.getServletPath(); // '/member/login.do'

 

  • map에서 해당경로에 매핑된 CommandProcess 객체를 찾는다.
CommandProcess com = (CommandProcess) map.get(category); // LoginService 인스턴스

 

  • com.requestPro(request, response) 메서드를 호출하여 요청을 처리한다.
String view = com.requestPro(request, response);

 

  • 반환된 view 경로로 RequestDispatcher를 사용해 포워딩한다
RequestDispatcher dispatcher = request.getRequestDispatcher(view);
dispatcher.forward(request, response);

CommandProcess.java(부모)

           LoginService.java (상속받음)

 

 LoginService.java 

package member.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.control.CommandProcess;

import member.bean.MemberDTO;
import member.dao.MemberDAO;

public class LoginService implements CommandProcess {

	@Override
	public String requestPro(HttpServletRequest request, HttpServletResponse response) throws Throwable {
		//데이터
	    request.setCharacterEncoding("UTF-8");
	    String id = request.getParameter("id");
	    String pwd = request.getParameter("pwd");

	    //DB
	    MemberDAO memberDAO = MemberDAO.getInstance();
	    MemberDTO memberDTO = memberDAO.memberLogin(id, pwd);
	    
	    if(memberDTO == null)
	    	return "/member/loginFail.jsp";
	    else {
	    	//세션
	    	HttpSession session = request.getSession(); //세션생성
	    
	    	// 세션에 저장
	        session.setAttribute("memName", memberDTO.getName());
	        session.setAttribute("memId", id);
	        session.setAttribute("memEmail", memberDTO.getEmail1() + "@" + memberDTO.getEmail2());
	    	
	        session.setAttribute("memDTO", memberDTO);
	        
	        return "/member/loginOk.jsp";
	    }
	}

}

 

1. 데이터 받음 ( id, pwd )

2. DB로 간다. ( MemberDAO)

3. return 해준다. (     "/member/loginOk.jsp"      "/member/loginFail.jsp"    )


loginOk.jsp

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

${sessionScope.memName}

 

sessionScope: 세션에 저장된 값을 참조할 때 사용한다. 세션은 사용자가 웹 애플리케이션에 접속한 순간부터 접속을 종료하거나 일정 시간이 지나기 전까지 유지되는 정보를 저장하는 공간이다.

 

sessionScope에 저장된 memName이라는 속성 값을 가져옴

 


loginFail.jsp

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

 

return시키면 반드시 ControlServelt.java로 왔다가

jsp로 가는 것이다 !!!!

 

그 때 오는 jsp는 위에서 우리가 return 해준 값으로 !!

 

마지막으로 ajax로 도착 !!!


memberLoginForm.jsp

<script src="../js/member.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-3.7.1.min.js"></script>
<script type="text/javascript">
$('#loginBtn').click(function(event) {
    event.preventDefault(); // 기본 제출 동작 방지
    
    $('#idDiv').empty();
    $('#pwdDiv').empty();
    
    if ($('#id').val() == '') {
        $('#idDiv').html('아이디를 입력하세요.');
    } else if ($('#pwd').val() == '') {
        $('#pwdDiv').html('비밀번호를 입력하세요.');
    } else {
        $.ajax({
            type: 'POST',
            url: '/memberMVC/member/login.do',
            data: {
                'id': $('#id').val(),
                'pwd': $('#pwd').val()
            },
            dataType: 'text', // 서버로부터 순수한 텍스트만 받음
            success: function(data) {
               console.log(data);
                if (data.trim() === 'fail') {
                    alert("아이디 또는 비밀번호가 틀렸습니다.");
                } else {
                    alert(data.trim() + "님이 로그인하였습니다.");                    
                }
            },
            error: function(e) {
                console.log(e);
            }
        });
    }
});

</script>


홈화면

memberLoginForm.jsp - 로그인 성공하면 홈화면으로 이동하게하기 (여기서도 jsp로 가라 !! 하면 안된다 !!)

        success: function(data) {
           console.log(data);
            if (data.trim() === 'fail') {
                alert("아이디 또는 비밀번호가 틀렸습니다.");
            } else {
                alert(data.trim() + "님이 로그인하였습니다.");                    
                location.href = '/memberMVC/index.do'
            }
        },

 


command.properties - /index.do 추가하기

#요청=클래스명
#메인화면
/index.do=main.IndexService
#회원가입
/member/writeForm.do=member.service.WriteFormService
/member/checkId.do=member.service.CheckIdService

#로그인
/member/loginForm.do=member.service.LoginFormService
/member/login.do=member.service.LoginService

Package: main

IndexService.java

package main;

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

import com.control.CommandProcess;

public class IndexService implements CommandProcess {

	@Override
	public String requestPro(HttpServletRequest request, HttpServletResponse response) throws Throwable {
		return "/index.jsp";
	}

}

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>메인화면</title>
<style type="text/css">
body {
	background-color: #FFE2FA;
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
}

h2 {
    margin-top: 50px;
}

.nav-bar {
    margin-top: 20px;
    padding: 10px 20px;
}

.nav-bar h3 {
    display: inline-block;
    margin: 0 10px;
}

.nav-bar h3 a {
    text-decoration: none;
    font-size: 16px;
    padding: 8px 12px;
    color: black;
}

.nav-bar h3 a:hover {
    color: gray;
}
</style>
</head>
<body>
    <h2>메인화면</h2>
    <div class="nav-bar">
    <c:if test="${sessionScope.memId == null}">
        <h3><a href="/memberMVC/member/writeForm.do">회원가입</a></h3>
        <h3><a href="/memberMVC/member/loginForm.do">로그인</a></h3>
    </c:if>
    
    <c:if test="${sessionScope.memId != null}">
        <h3><a href="/memberMVC/member/logout.do">로그아웃</a></h3>
        <h3><a href="/memberMVC/member/updateForm.do">회원정보수정</a></h3>
   </c:if>
    </div>
</body>
</html>

 

http://localhost:8080/memberMVC/index.do


로그아웃

command.properties - 로그아웃 추가

#요청=클래스명
#메인화면
/index.do=main.IndexService
#회원가입
/member/writeForm.do=member.service.WriteFormService
/member/checkId.do=member.service.CheckIdService

#로그인
/member/loginForm.do=member.service.LoginFormService
/member/login.do=member.service.LoginService
/member/logout.do=member.service.LogoutService

LogoutService.java

package member.service;

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

import com.control.CommandProcess;

public class LogoutService implements CommandProcess {

	@Override
	public String requestPro(HttpServletRequest request, HttpServletResponse response) throws Throwable {
		HttpSession session = request.getSession();// 세션 생성
		session.removeAttribute("memName");
		session.removeAttribute("memId");
					
		//session.invalidate();
		return "/member/memberLogout.jsp";
	}

}

이미지 눌렀을 때 index.do로 가게 다 바꾸기 !! 

 

<img src="../image/free-icon-love-4096198.png" alt="홈" width="60" height="60" onclick="location.href='/memberMVC/index.do'" />


 

회원가입

 

memberLoginForm.jsp

         <tr>
             <td colspan="2" align="center">
                 <input type="submit" value="로그인" id="loginBtn"/>
                 <input type="button" value="회원가입" onclick="location.href='/memberMVC/member/writeForm.do'" />
             </td>
         </tr>

memberWriteForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입 페이지</title>
<style type="text/css">
body {
    background-color: #FFE2FA;
    font-family: 'Arial', sans-serif;
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 80vh;
    flex-direction: column;
}

table {
    border-collapse: collapse;
    border-radius: 10px;
    background-color: white;
    width: 700px;
    padding: 15px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    margin: 0 auto;
}

th, td {
    padding: 8px 10px;
    text-align: left;
    font-size: 14px;
}

th {
    color: #333;
    font-size: 16px;
}

td {
    color: #333;
}

div {
    color: red;
    font-size: 8pt;
    font-weight: bold;
    margin-top: 5px;
}

input[type="text"], input[type="password"], select {
     margin-top: 5px;
    padding: 5px;
    border: 1px solid #CCC;
    border-radius: 5px;
    box-sizing: border-box;
}

input[type="text"][size], input[type="password"][size] {
    width: auto;
}

input[type="button"], input[type="submit"], input[type="reset"] {
    background-color: #FF9ADB;
    border: none;
    font-size: 14px;
    padding: 6px 10px;
    border-radius: 5px;
    cursor: pointer;
    color: white;
    transition: background-color 0.3s ease;
    margin: 4px;
}

input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover {
    background-color: #FF70C0;
}

img {
    margin-bottom: 15px;
    cursor: pointer;
    display: block;
}

table td[colspan="2"] {
    text-align: center;
}
</style>
</head>
<body>
<img src="../image/free-icon-love-4096198.png" alt="홈" width="60" height="60" onclick="location.href='/memberMVC/index.do'" />
<form name="memberWriteForm" method="post" action="/memberMVC/member/write.do">
    <table>
        <tr>
            <th>이름</th>
            <td>
                <input type="text" name="name" id="name" placeholder="이름 입력" size="15"/>
                <div id="nameDiv"></div>
            </td>
        </tr>
        
        <tr>
            <th>아이디</th>
            <td>
                <input type="text" name="id" id="id" placeholder="아이디 입력" size="15"/>
                <input type="hidden" id="check" value=""/>
                <div id="idDiv"></div>
            </td>
        </tr>
        
        <tr>
            <th>비밀번호</th>
            <td>
                <input type="password" name="pwd" id="pwd" placeholder="비밀번호 입력" size="25"/>
                <div id="pwdDiv"></div>    
            </td>
        </tr>
        
        <tr>
            <th>재확인</th>
            <td>
                <input type="password" name="repwd" id="repwd" placeholder="비밀번호 입력" size="25"/>
                <div id="repwdDiv"></div>    
            </td>
        </tr>
        
        <tr>
            <th>성별</th>
            <td>
                <input type="radio" name="gender" value="0" checked/> 남자
                <input type="radio" name="gender" value="1"/> 여자
            </td>
        </tr>
        
        <tr>
            <th>이메일</th>
            <td>
                <input type="text" name="email1" size="15"/> @
                <input type="text" name="email2" id="email2" size="15"/>
                <input type="text" name="email3" id="email3" list="email3_list" size="15" oninput="change()"/>
                <datalist id="email3_list">
                    <option value="직접입력">직접입력</option>
                    <option value="naver.com"></option>
                    <option value="gmail.com"></option>
                    <option value="daum.net"></option>
                </datalist>                        
            </td>
        </tr>
        
        <tr>
            <th>휴대전화</th>
            <td>
                <select name="tel1" style="width: 70px;">
                    <option value="010">010</option>
                    <option value="011">011</option>
                    <option value="019">019</option>
                </select>
                -
                <input type="text" name="tel2" size="4" maxlength="4"/>
                -
                <input type="text" name="tel3" size="4" maxlength="4"/>
            </td>
        </tr>
        
        <tr>
            <th>주소</th>
            <td>
                <input type="text" name="zipcode" id="zipcode" placeholder="우편번호" size="6" readonly/>
                <input type="button" value="우편번호 검색" onclick="checkPost()"/><br>
                <input type="text" name="addr1" id="addr1" placeholder="주소" size="50" readonly/><br>
                <input type="text" name="addr2" id="addr2" placeholder="상세주소" size="50"/>
            </td>
        </tr>
        
        <tr>
            <td colspan="2" align="center">
                <input type="submit" value="회원가입" onclick="memberWrite(event)" />
                <input type="reset" value="다시입력" />
            </td>
        </tr>
    </table>
</form>
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-3.7.1.min.js"></script>
<script type="../js/member.js"></script>
</body>
</html>
<script type="text/javascript">
// 아이디 중복 검사
$(function () {
    $('#id').on('focusout', function(){
        $('#idDiv').empty(); // 메시지 초기화
        let id = $('#id').val(); 

        if (id === '') {
            $('#idDiv').html('아이디를 입력하세요.').css('color', 'red'); 
            return;
        }

        $.ajax({
            type: 'post',
            url: '/memberMVC/member/checkId.do', 
            data: {'id': id},
            dataType: 'text',
            success: function(data){			   
                if (data.trim() === 'exist') {
                    $('#idDiv').html('이미 사용 중인 아이디입니다.').css('color', 'red');
                } else {
                    $('#idDiv').html('사용가능한 아이디입니다.').css('color', 'green'); 
                    $('#check').val($('#id').val()); // 중복 체크가 완료된 아이디 저장
                }
            },
            error: function(e){
                console.log(e);
            }
        });
    });
});
</script>
</body>
</html>

member.js

//회원가입
function memberWrite(e){
    let isValid = true; // 유효성 검사를 통과하면 true, 아니면 false

    document.getElementById("nameDiv").innerHTML = "";
    document.getElementById("idDiv").innerHTML = "";
    document.getElementById("pwdDiv").innerHTML = "";
    document.getElementById("repwdDiv").innerHTML = "";
    
    if(document.memberWriteForm.name.value == ""){
        document.getElementById("nameDiv").innerHTML = "이름을 입력해주세요.";
		e.preventDefault();
		isValid = false;
    }
    
    if(document.getElementById("id").value == ""){
        document.getElementById("idDiv").innerHTML = "아이디를 입력해주세요.";
        e.preventDefault();
		isValid = false;
    }

    if(document.getElementById("pwd").value == ""){
        document.getElementById("pwdDiv").innerHTML = "비밀번호를 입력해주세요.";
		e.preventDefault();
		isValid = false;
    }
    
    if(document.getElementById("pwd").value != document.getElementById("repwd").value){
        document.getElementById("repwdDiv").innerHTML = "비밀번호가 맞지 않습니다.";
		e.preventDefault();
		isValid = false;
    }

    // 중복 체크 확인
    if(document.getElementById("check").value != document.getElementById("id").value){
        document.getElementById("idDiv").innerHTML = "중복체크를 해주세요!";
		e.preventDefault();
		isValid = false;
    }

    if(isValid)
		 document.memberWriteForm.submit();
}

command.properties

#회원가입
/member/writeForm.do=member.service.WriteFormService
/member/checkId.do=member.service.CheckIdService
/member/write.do=member.service.WriteService

WriteService.java

한글처리할 필요없다. 왜? 항상 ControlServlet.java로 가서 execute에서 한글처리를 했기 때문 !

package member.service;

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

import com.control.CommandProcess;

import member.bean.MemberDTO;
import member.dao.MemberDAO;

public class WriteService implements CommandProcess {

	@Override
	public String requestPro(HttpServletRequest request, HttpServletResponse response) throws Throwable {
		
		//데이터
		String name = request.getParameter("name");
		String id = request.getParameter("id");
		String pwd = request.getParameter("pwd");
		String gender = request.getParameter("gender");
		String email1 = request.getParameter("email1");
		String email2 = request.getParameter("email2");
		String tel1 = request.getParameter("tel1");
		String tel2 = request.getParameter("tel2");
		String tel3 = request.getParameter("tel3");
		String zipcode = request.getParameter("zipcode");
		String addr1 = request.getParameter("addr1");
		String addr2 = request.getParameter("addr2");
		
		MemberDTO memberDTO = new MemberDTO();
		memberDTO.setName(name);
		memberDTO.setId(id);
		memberDTO.setPwd(pwd);
		memberDTO.setGender(gender);
		memberDTO.setEmail1(email1);
		memberDTO.setEmail2(email2);
		memberDTO.setTel1(tel1);
		memberDTO.setTel2(tel2);
		memberDTO.setTel3(tel3);
		memberDTO.setZipcode(zipcode);
		memberDTO.setAddr1(addr1);
		memberDTO.setAddr2(addr2);
		
		//DB
		MemberDAO memberDAO = MemberDAO.getInstance();
		memberDAO.memberWrite(memberDTO);
				
		return "/member/memberWrite.jsp";
	}

}

 


memberWrite.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<script type="text/javascript">
window.onload = function(){
	alert("회원가입을 축하합니다.");
	location.href = "/memberMVC/index.do"
}
</script>
</body>
</html>

회원정보 수정

memberUpdateForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="member.bean.MemberDTO"%>
<%@page import="member.dao.MemberDAO"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원정보 수정</title>
<style type="text/css">
body {
    background-color: #FFD7F8;
    font-family: 'Arial', sans-serif;
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 80vh;
    flex-direction: column;
}

table {
    border-collapse: collapse;
    border-radius: 10px;
    background-color: white;
    width: 700px;
    padding: 15px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    margin: 0 auto;
}

th, td {
    padding: 8px 10px;
    text-align: left;
    font-size: 14px;
}

th {
    color: #333;
    font-size: 16px;
}

td {
    color: #333;
}

div {
    color: red;
    font-size: 8pt;
    font-weight: bold;
    margin-top: 5px;
}

input[type="text"], input[type="password"], select {
   margin-top: 5px;
    padding: 5px;
    border: 1px solid #CCC;
    border-radius: 5px;
    box-sizing: border-box;
}

input[type="text"][size], input[type="password"][size] {
    width: auto;
}

input[type="button"], input[type="submit"], input[type="reset"] {
    background-color: #FF9ADB;
    border: none;
    font-size: 14px;
    padding: 6px 10px;
    border-radius: 5px;
    cursor: pointer;
    color: white;
    transition: background-color 0.3s ease;
    margin: 4px;
}

input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover {
    background-color: #FF70C0;
}

img {
    margin-bottom: 15px;
    cursor: pointer;
    display: block;
}

table td[colspan="2"] {
    text-align: center;
}
</style>
</head>
<body>
<img src="../image/free-icon-love-4096198.png" alt="홈" width="60" height="60" onclick="location.href='../index.jsp'" style="cursor: pointer;" />
<form name="memberUpdateForm" method="post" action="memberMVC/member/update.do">

    <table>
        <tr>
            <th>이름</th>
            <td>
                <input type="text" name="name" id="name" value="${memberDTO.name}" size="15"/>
                <div id="nameDiv"></div>
            </td>
        </tr>
        
        <tr>
            <th>아이디</th>
            <td>
                <input type="text" name="id" id="id" value="${memberDTO.id}" readonly />
            </td>
        </tr>
        
        <tr>
            <th>비밀번호</th>
            <td>
                <input type="password" name="pwd" id="pwd" placeholder="비밀번호 입력" size="25"/>
                <div id="pwdDiv"></div>    
            </td>
        </tr>
        
        <tr>
            <th>재확인</th>
            <td>
                <input type="password" name="repwd" id="repwd" placeholder="비밀번호 입력" size="25"/>
                <div id="repwdDiv"></div>    
            </td>
        </tr>
        
        <tr>
            <th>성별</th>
            <td>
               <input type="radio" name="gender" value="0" ${memberDTO.gender == '0' ? 'checked' : ''}/> 남자
			   <input type="radio" name="gender" value="1" ${memberDTO.gender == '1' ? 'checked' : ''}/> 여자
            </td>
        </tr>
        
        <tr>
            <th>이메일</th>
            <td>
                <input type="text" name="email1" value="${memberDTO.email1}" size="15"/> @
                <input type="text" name="email2" id="email2" value="${memberDTO.email2}" size="15"/>
                <input type="text" name="email3" id="email3" list="email3_list" size="15" oninput="change()"/>
                <datalist id="email3_list">
                    <option value="직접입력">직접입력</option>
                    <option value="naver.com"></option>
                    <option value="gmail.com"></option>
                    <option value="daum.net"></option>
                </datalist>                        
            </td>
        </tr>
        
        <tr>
            <th>휴대전화</th>
            <td>
                <select name="tel1" style="width: 70px;">
                    <option value="010">010</option>
                    <option value="011">011</option>
                    <option value="019">019</option>
                </select>
                -
                <input type="text" name="tel2" value="${memberDTO.tel2}" size="4" maxlength="4"/>
                -
                <input type="text" name="tel3" value="${memberDTO.tel3}" size="4" maxlength="4"/>
            </td>
        </tr>
        
        <tr>
            <th>주소</th>
            <td>
                <input type="text" name="zipcode" id="zipcode" value="${memberDTO.zipcode}" placeholder="우편번호" size="6" readonly/>
                <input type="button" value="우편번호 검색" onclick="checkPost()"/><br>
                <input type="text" name="addr1" id="addr1" value="${memberDTO.addr1}" placeholder="주소" size="50" readonly/><br>
                <input type="text" name="addr2" id="addr2" value="${memberDTO.addr2}" placeholder="상세주소" size="50"/>
            </td>
        </tr>
        
        <tr>
            <td colspan="2" align="center">
                <input type="submit" value="회원정보수정" id="updateBtn"/>
                <input type="reset" value="다시입력" onclick="location.reload()"/>
            </td>
        </tr>
    </table>
</form>
<script type="text/javascript" src="http://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script src="../js/member.js"></script>
<script type="text/javascript">
window.onload = function(){
   document.memberUpdateForm.gender['${memberDTO.gender}'].checked = true; 
   document.memberUpdateForm.tel1.value = '${memberDTO.tel1}';
}
</script>
</body>
</html>

 

사용자가 수정한 회원 정보를 폼에 입력하고 "회원정보수정" 버튼을 클릭하면

폼 데이터는 POST 방식으로 member/update.do로 전달된다.

 


command.properties

#회원정보 수정
/member/updateForm.do=member.service.UpdateFormService

UpdateFormService.java

회원 정보 수정 화면으로 이동할 때 사용자의 정보를 불러오는 역할을 한다.

package member.service;

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

import com.control.CommandProcess;

import member.bean.MemberDTO;
import member.dao.MemberDAO;

public class UpdateFormService implements CommandProcess {

	@Override
	public String requestPro(HttpServletRequest request, HttpServletResponse response) throws Throwable {
        // 세션에서 사용자 ID를 가져옴
        HttpSession session = request.getSession();
        String id = (String) session.getAttribute("memId");

        // DB에서 회원 정보 가져오기
        MemberDAO memberDAO = MemberDAO.getInstance();
        MemberDTO memberDTO = memberDAO.getMember(id);

        // 회원 정보를 request에 저장 (JSP에서 사용)
        request.setAttribute("memberDTO", memberDTO);
        
		return "/member/memberUpdateForm.jsp";
	}

}

 

 

  • UpdateFormService는 세션에서 사용자 ID를 가져와 데이터베이스에서 해당 회원 정보를 조회하고 이를 memberUpdateForm.jsp로 전달한다. 불러온 정보를 보고 이제 회원정보 수정을 할 수 있는 것이다 !

member.js

//회원정보 수정
$('#updateBtn').on('click', function(event){
    event.preventDefault();

    $('#nameDiv').empty();
    $('#pwdDiv').empty();
    $('#repwdDiv').empty();
    let isValid = true;
    
    // 이름 검사
    if($('#name').val().trim() == ''){
        $('#nameDiv').html('비밀번호를 입력하세요.').css('color', 'red');
        $('#name').focus();
        isValid = false;
    }
    
    // 비밀번호 검사
    if($('#pwd').val().trim() == ''){
        $('#pwdDiv').html('비밀번호를 입력하세요.').css('color', 'red');
        $('#user_pwd').focus();
        isValid = false;
    }
    
    // 비밀번호 확인 검사
    if($('#repwd').val() == ''){
        $('#repwdDiv').html('비밀번호 확인을 해주세요.').css('color', 'red');
        $('#repwd').focus();
        isValid = false;
    } else if($('#pwd').val() != $('#repwd').val()){
        $('#repwdDiv').html('비밀번호가 일치하지 않습니다.').css('color', 'red');
        $('#repwdDiv').val('');
        $('#repwdDiv').focus();
        isValid = false;
    }
    
    if(isValid){
        $.ajax({
            type: 'post',
            url: ' ${ pageContext.request.contextPath }/member/update.do',
            data: $('form').serialize(),
            dataType: 'text',
            success: function(data){
                alert('회원정보가 수정되었습니다.');
                window.location.href = " ${ pageContext.request.contextPath }/index.do";
            },
            error: function(e){
                console.log(e);
            }
        });
    }
});

command.properties

/member/update.do=member.service.UpdateService

UpdateService.java

수정된 회원 정보를 데이터베이스에 저장하는 역할을 한다.

public class UpdateService implements CommandProcess {

    @Override
    public String requestPro(HttpServletRequest request, HttpServletResponse response) throws Throwable {
        // 폼 데이터 가져오기
        String id = request.getParameter("id");
        String name = request.getParameter("name");
        String pwd = request.getParameter("pwd");
        String gender = request.getParameter("gender");
        String email1 = request.getParameter("email1");
        String email2 = request.getParameter("email2");
        String tel1 = request.getParameter("tel1");
        String tel2 = request.getParameter("tel2");
        String tel3 = request.getParameter("tel3");
        String zipcode = request.getParameter("zipcode");
        String addr1 = request.getParameter("addr1");
        String addr2 = request.getParameter("addr2");

        // DTO에 데이터 저장
        MemberDTO memberDTO = new MemberDTO();
        memberDTO.setId(id);
        memberDTO.setName(name);
        memberDTO.setPwd(pwd);
        memberDTO.setGender(gender);
        memberDTO.setEmail1(email1);
        memberDTO.setEmail2(email2);
        memberDTO.setTel1(tel1);
        memberDTO.setTel2(tel2);
        memberDTO.setTel3(tel3);
        memberDTO.setZipcode(zipcode);
        memberDTO.setAddr1(addr1);
        memberDTO.setAddr2(addr2);

        // 데이터베이스 업데이트
        MemberDAO memberDAO = MemberDAO.getInstance();
        memberDAO.memberUpdate(memberDTO);

        return "../index.jsp";
    }
}

 

  • UpdateService는 사용자가 제출한 폼 데이터를 request.getParameter()를 통해 받아 MemberDTO 객체에 저장하게된다.
  • 그리고  MemberDAO를 통해 데이터베이스에 변경된 정보를 업데이트하고 완료되면 홈 화면으로 리다이렉트한다.

원래는 ~~~Service.java 파일에서 jsp파일을 ControlService.java 파일로 가서 

view = com.requestPro(request, response); 여기서 받아서 

//forward

RequestDispatcher dispatcher = request.getRequestDispatcher(view); //상대번지

dispatcher.forward(request, response); //제어권 넘기기

 

forward하는 작업을 해준다 !!

 

근데 여기서는 update하고 나서 따로 jsp파일로 가도 할게 없다 !

그럴 때 어떻게 하면 좋을까 !?

밑에처럼 아예 return "none"을 반환하는 것이다.

 

UpdataService.java

package member.service;

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

import com.control.CommandProcess;

import member.bean.MemberDTO;
import member.dao.MemberDAO;

public class UpdateService implements CommandProcess {

    @Override
    public String requestPro(HttpServletRequest request, HttpServletResponse response) throws Throwable {

        String id = request.getParameter("id");
        String name = request.getParameter("name");
        String pwd = request.getParameter("pwd");
        String gender = request.getParameter("gender");
        String email1 = request.getParameter("email1");
        String email2 = request.getParameter("email2");
        String tel1 = request.getParameter("tel1");
        String tel2 = request.getParameter("tel2");
        String tel3 = request.getParameter("tel3");
        String zipcode = request.getParameter("zipcode");
        String addr1 = request.getParameter("addr1");
        String addr2 = request.getParameter("addr2");

        MemberDTO memberDTO = new MemberDTO();
        memberDTO.setId(id);  // 세션에서 가져온 ID 설정
        memberDTO.setName(name);
        memberDTO.setPwd(pwd);
        memberDTO.setGender(gender);
        memberDTO.setEmail1(email1);
        memberDTO.setEmail2(email2);
        memberDTO.setTel1(tel1);
        memberDTO.setTel2(tel2);
        memberDTO.setTel3(tel3);
        memberDTO.setZipcode(zipcode);
        memberDTO.setAddr1(addr1);
        memberDTO.setAddr2(addr2);

        // DB
        MemberDAO memberDAO = MemberDAO.getInstance();
        memberDAO.memberUpdate(memberDTO);  // 회원 정보 업데이트

        return "none"; 
    }
}

그럼 이제 여기로 넘와서 view의 값이 none이면 그냥 바로 ajax로 return하게 하는 것이다.

ControlService.java

	protected void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println();
		
		if(request.getMethod().equals("POST")) 
			request.setCharacterEncoding("UTF-8");
		
		//http://localhost:8080/memberMVC/member/writeForm.do
		//요청한 URL에서 "/member/writeForm.do" 뜯어오기
		String category = request.getServletPath(); //'/member/checkId.do' 추출
		System.out.println("category = " + category);
		
		// Map을 이용하여 Key에 해당하는 값을 꺼내온다.  member.service.WriteFormService
		CommandProcess com = (CommandProcess)map.get(category); // 자식 = (자식)부모  // CheckIdService를 찾음
		
		String view = null;
		
		try {
			view = com.requestPro(request, response);
		} catch (Throwable e) {
			e.printStackTrace();
		}
		
		if(view.equals("none")) 
			return;
		
		//forward
		RequestDispatcher dispatcher = request.getRequestDispatcher(view); //상대번지
		dispatcher.forward(request, response); //제어권 넘기기
	}

여기서 return하게 되면

 

member.js

if(isValid){
        $.ajax({
            type: 'post',
            url: '/memberMVC/member/update.do',
            data: $('form').serialize(),
            dataType: 'text',
            success: function(data){
                alert('회원정보가 수정되었습니다.');
                window.location.href = "../index.jsp";
            },
            error: function(e){
                console.log(e);
            }
        });
    }

 

여기로 와서 회원정보가 수정되었습니다가 뜨는 것 !!

 


/memberMVC 이런식으로 다 적게되면 나중에 프로젝트명이 바뀌면 굉장히 번거로워진다.

그러므로 밑에처럼 하면 좋다 !!

 

index.jsp

<body>
    <h2>메인화면</h2>
    
    Context = ${pageContext.request.getContextPath()}
    <div class="nav-bar">
    <c:if test="${sessionScope.memId == null}">
        <h3><a href="/memberMVC/member/writeForm.do">회원가입</a></h3>
        <h3><a href="/memberMVC/member/loginForm.do">로그인</a></h3>
    </c:if>
    
    <c:if test="${sessionScope.memId != null}">
        <h3><a href="/memberMVC/member/logout.do">로그아웃</a></h3>
        <h3><a href="/memberMVC/member/updateForm.do">회원정보수정</a></h3>
   </c:if>
    </div>
</body>

 

Context = ${pageContext.request.getContextPath()}
Context = ${ pageContext.request.contextPath }

 

두 개 다 같은 코드

이유 : 메소드 호출시 접두사 set/get를 생략 할 수 있다 메소드명을 변수명처럼 사용 할 수 있다


<c:set var="context" value="${ pageContext.request.contextPath }"></c:set>
<body>
    <h2>메인화면</h2>
    
    Context = ${ pageContext.request.contextPath }
    <c:set var="context" value="${ pageContext.request.contextPath }"></c:set>
    <div class="nav-bar">
    <c:if test="${sessionScope.memId == null}">
        <h3><a href="${context}/member/writeForm.do">회원가입</a></h3>
        <h3><a href="${context}/member/loginForm.do">로그인</a></h3>
    </c:if>
    
    <c:if test="${sessionScope.memId != null}">
        <h3><a href="${context}/member/logout.do">로그아웃</a></h3>
        <h3><a href="${context}/member/updateForm.do">회원정보수정</a></h3>
   </c:if>
    </div>
</body>

memberWriteForm.jsp

<form name="memberWriteForm" method="post" action="${ pageContext.request.contextPath }/member/write.do">

 

 

근데 약간 저걸로 다 바꿨을 때 오류나는 부분들이 있다. 얘를 들면 member.js는 바꾸면 얘가 인식을 못한다.

그 부분은 바꾸면 안될듯~?