국비교육과정 정리/Java

[JSP실습] 회원가입 구현하기

백설마을꿀단지 2022. 12. 6.

1. include 활용해서 header, footer 추출하기

전체 페이지에서 공통으로 사용되는 부분이 있다면 따로 jsp 파일을 만들어서 include 해서 사용하는 것이

코드를 간결화시킬 수 있다.

2. 서블릿(Servlet) 작성

다른 페이지로 이동하는 것은 일반적으로 a 태그를 사용하지만 MVC Modole2에서는 모든 요청이 하나의 서블릿을
통해 전달이 되고 서블릿에서 요청을 처리하여 그에 걸맞는 jsp 페이지를 포워딩하도록 해야함

1) 서블릿은 get과 post로 나뉘지만 이를 구분하지 않고 통합해서 작동될 수 있도록 doAction()  메서드를 만들어서
  get과 post를 통합시킨다.

2) post로 들어올 경우를 대비해서 한글처리 및 요청경로 통일 작업을 진행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@WebServlet("*.user")
public class UserController extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
                throws ServletException, IOException {
        doAction(request, response); //do, post 통합
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
                throws ServletException, IOException {
        doAction(request, response); //do, post 통합
    }
 
    //get, post 하나로 묶는 메서드
    protected void doAction(HttpServletRequest request, HttpServletResponse response) 
                throws ServletException, IOException {
 
        //한글처리
        request.setCharacterEncoding("utf-8");
 
        //요청분기
        String uri = request.getRequestURI();
        String path = request.getContextPath();
        
        String command = uri.substring(path.length());
        
        System.out.println("요청경로: " + command);
 
        UserService service = new UserServiceImpl();
cs

3. 요청경로에 따라 알맞은 jsp가 실행될 수 있도록 switch문으로 나눔

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
switch (command) {
        case "/user/user_join.user":
            
            request.getRequestDispatcher("user_join.jsp").forward(request,response);
            
            break;
        case "/user/joinForm.user":
            
            int result = service.join(request, response);
            
            if(result >= 1) { //아이디 중복되었을 경우
                //메시지
                request.setAttribute("msg""중복된 아이디 or 이메일입니다."); //메시지를 보내야하기에 포워드 사용
                request.getRequestDispatcher("user_join.jsp").forward(request, response);
                
                
            }else { //가입 성공
                
                //request.getRequestDispatcher("user_login.jsp").forward(request, response);
                //response.sendRedirect("user_login.jsp"); //MVC2 방식을 위반함 /컨트롤러 안타고 바로 가기 때문에
                response.sendRedirect("user_login.user");
            }
            break;
        
        case "/user/user_login.user"//로그인페이지
            
            request.getRequestDispatcher("user_login.jsp").forward(request, response);
            break;
        
        case "/user/loginForm.user"//로그인요청
            
            UserVO vo = service.login(request, response);
        
            if(vo == null) { //로그인 실패
                request.setAttribute("msg""아이디 비밀번호를 확인하세요");
                request.getRequestDispatcher("user_login.jsp").forward(request, response);
            }else { //로그인 성공
                //세션에 아이디, 이름을 저장
                HttpSession session = request.getSession();
                session.setAttribute("user_id", vo.getId());
                session.setAttribute("user_name", vo.getName());
                
                //마이페이지로 이동
                response.sendRedirect("user_mypage.user");
                
            }
            
            break;
        
        case "/user/user_mypage.user":
            
            request.getRequestDispatcher("user_mypage.jsp").forward(request, response);
            
            break;
 
        default:
            break;
        }
cs

3. 회원가입

회원가입(join)의 요청을 진행하는 jsp 페이지로 포워딩한다.(Redirect는 MVC Model2 에 위배되는 방식)

1) 회원가입을 담당하는 user_join.jsp 에서 필요한 값들을 form태그를 통해 입력받고 이를 다시 input submit 태그를 통해서 값들을 전달해주어야 한다. form 태그 action 에 적힌 링크로 값들이 전달되는데 요청이므로 서블릿으로
전달해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<form action="joinForm.user" method="post">
 
<span style = "color" : red>${msg }</span>
    
<table>
    <tr>
        <td>아이디</td>
        <td><input type="text" name="id" placeholder="4글자~8글자" pattern = "\w{4,8}" required = "required"></td>
    </tr>
    <tr>
        <td>비밀번호</td>
        <td><input type="password" name="pw" pattern = "\w{4,8}" required = "required"></td>
    </tr>
    <tr>
        td>이름</td>
        <td><input type="text" name="name" pattern = "[가-힣]{3,}"></td>
    </tr>
    <tr>
        <td>이메일</td>
        <td><input type="email" name="email"></td>
    </tr>
    <tr>
        <td>성별</td>
        <td>
        <input type="radio" name="gender" value = "m" checked = "checked">남자
        <input type="radio" name="gender" value = "f"> 여자
        </td>
    </tr>
                    
</table>
    
    <input type="submit" value="가입">
    <!-- button은 JS로 기능을 추가한다. -->
    <input type="button" value="로그인하기" onclick="location.href = 'user_login.user'">
</form>
cs

 

2) 서블릿에 너무 많은 코드가 작성되면 가독성이 떨어지므로 서블릿의 역할을 분담하는 메서드 작성을 위해 새로운
클래스를 생성하여 메서드를 작성한다.. (UserServiceImpl)

3) 값들을 받아야하기에 매개변수로 HttpServletRequest request, HttpServletResponse response이 들어와야 한다.

 

4) 이후 request.getParameter 메서드를 통해 user_join.jsp에서 입력되었던 값들을 받아온다.

 

5) 여기서 입력되었던 값들 중 중복이 발생되서는 안되는 값(id, email...)이 있을 경우 예외 처리를 해주어야 하는데 중복을 확인하기 위해서는 회원의 정보가 담겨있는 database가 활용되어야 한다. sql 쿼리문을 java에서 작업해야하므로
JDBC활용을 위한 DAO, VO 클래스가 새로 만들어져야 한다.

 

6) DAO의 객체는 여러 개 생성될 필요가 없기 때문에 Singleton 형식으로 설계된다.

7) sql 쿼리문을 통해 id 중복확인을 하는 메서드를 작성한다. 쿼리문에서 중복되는 값의 개수를 구하는데 개수가 0이라는 것은 중복값이 없다는 것으로 0과 1 이상일 떄로 나누어 중복을 확인할 수 있고 중복확인의 결과를 int로 반환한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
public class UserDAO {
    
    //UserDAO는 불필요하게 여러 개 만들어질 필요가 없기 때문에
    //한 개의 객체만 만들어지도록 Singleton 형식으로 설계
    
    //1. 나 자신의 객체를 생성해서 1개로 제한
    private static UserDAO instance = new UserDAO();
    
    
    //2. 직접 객체를 생성할 수 없도록 생성자에 private
    private UserDAO() {
        //드라이버 클래스는 어차피 생성되어야 하므로 생성자에 포함
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        } catch (Exception e) {
            System.out.println("드라이버클래스 로드에러");
        }
    }
    
    
    //3. 외부에서 객체 생성을 요구할 때 getter 메서드를 통해 1번의 객체를 반환
    public static UserDAO getInstance() {
        return instance;
    }
 
    
    //4. 필요한 데이터베이스 변수 선언
    public String url = "jdbc:oracle:thin:@localhost:1521:xe";
    public String uid = "jsp";
    public String upw = "jsp";
    Connection conn;
    PreparedStatement pstmt;
    ResultSet rs;
    
    
    //5. 메서드
    public int idCheck(String id, String email) {
        int result = 0;
        
        String sql = "select count(*) as total from users where id = ? or email = ?";
        
        try {
            conn = DriverManager.getConnection(url, uid, upw);
            pstmt = conn.prepareStatement(sql);
            
            pstmt.setString(1, id);
            pstmt.setString(2, email);
            
            rs = pstmt.executeQuery(); 
            if(rs.next()) {
                result = rs.getInt("total");
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, pstmt, rs);
        }
        
        return result;
    }
    
    //회원가입
    public void join(UserVO vo) {
    
        String sql = "insert into users values(?, ?, ?, ?, ?)";
        
        try    {
            conn = DriverManager.getConnection(url, uid, upw);
            pstmt = conn.prepareStatement(sql);
            
            pstmt.setString(1, vo.getId());
            pstmt.setString(2, vo.getPw());
            pstmt.setString(3, vo.getName());
            pstmt.setString(4, vo.getEmail());
            pstmt.setString(5, vo.getGender());
            
            pstmt.executeUpdate(); // 실행 후 성공 시 1 반환 실패 시 0 반환
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, pstmt, rs);
        }
        
    }
    
    //로그인
    public UserVO login(String id, String pw) {
        
        UserVO vo = null;
        
        String sql = "select * from users where id = ? and pw = ?";
        
        try {
            conn = DriverManager.getConnection(url,uid,upw);
            pstmt = conn.prepareStatement(sql);
            
            pstmt.setString(1, id);
            pstmt.setString(2, pw);
            
            rs = pstmt.executeQuery();
            
            if(rs.next()) { //로그인 성공 시 데이터가 조회되서 나타났을 것이다. 이를 vo에 담는다.
 
                String id2 = rs.getString("id");
                String name = rs.getString("name");
                String email = rs.getString("email");
                String gender = rs.getString("gender");
                
                vo = new UserVO(id2, null, name, email, gender);
            }
            
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, pstmt, rs);
        }
        
        
        return vo; //vo가 null이면 로그인 실패
    }
    
    
}
 
cs

 8) 다시 서블릿의 역할을 분담하기 위한 회원가입 메서드가 있는 UserServiceImpl로 돌아와서 중복값을 확인하는 DAO클래스의 idcheck메서드를 호출하 1이 리턴되면(중복O) 메시지를 띄우고 다시 로그인하도록 0이 리턴하면 (중복x) UserVO 클래스에 값들을 저장한다.

9) DAO클래스의 insert 쿼리가 담긴 메서드를 실행하여 db에 데이터를 저장하여 회원가입을 마친다.

 

10)회원가입이 끝난 이후 로그인페이지로 돌아가야는데 여기서는 Redirect가 허용된다. 왜? 페이지에서 다른페이지로 전환이 아닌 컨트롤러 내부에서 다른 요청을 하는 것이기 때문에 MVC Model 2에 위배되지 않는다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    public int join(HttpServletRequest request, HttpServletResponse response) {
        String id = request.getParameter("id");
        String pw = request.getParameter("pw");
        String name = request.getParameter("name");
        String email = request.getParameter("email");
        String gender = request.getParameter("gender");
        
        //아이디 or email 중복 검사 -> 없을 경우 가입
        
        UserDAO dao = UserDAO.getInstance();
        int result = dao.idCheck(id, email);
        
        if(result >= 1 ) { //ID or Email 중복
            return 1// 1을 중복이다 라는 의미로 사용
        }else//중복 x -> 가입
            UserVO vo = new UserVO(id, pw, name, email, gender);
            dao.join(vo);
            return 0// 0을 회원가입 성공 의미로 사용
        }
        
    }
cs

 

댓글