Servlet쇼핑몰2: 회원가입

MemberFrontController.java의 doProcess()메서드 추가 코드작성

  • 6번부터
  • 회원가입처리 -> 회원정보 입력창(view의 개념이 필요)
  • 모델2에서 페이지 이동은 무조건 ActionForward사용
  • 페이지이동방법은 2가지
    1. response : response.sendRedirect("./member/insertForm.jsp") => 웹주소가 .jsp끝나기때문에 우리가 원하는 모델2방식이 아니다.
    2. forward : RequestDispatcher사용 => 웹주소가 .me로 끝나기때문에 우리가 원하는 방식이지만 코드길이가 너무 길어진다. => ActionForward객체를 사용하면 편하다
      1
      2
      RequestDispatcher dis = request.getRequestDispatcher("./member/insertForm.jsp");
      dis.forward(request, response);
  • ActionForward객체로 특정주소에 대한 처리 후 response나 forward방식으로 페이지이동.
  • 모델2에서 페이지 이동은 무조건 ActionForward사용.
  • MemberJoinAction.java일때도 .me주소 출력
  • MemberJoinAction action = new MemberJoinAction()action = new MemberJoinAction();으로 변경하여 일회성이 아닌 여러번 사용가능하도록 만들기.
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
//3. doProcess()생성
protected void doProcess(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doProcess메서드 호출");

//4. 가상주소 가져오기 : 가지고 다닐 주소는 /*.me 앞부분의 주소는 필요가 없다.
String requestURI = req.getRequestURI();
StringBuffer requestURL = req.getRequestURL();
//uri와 url차이 -> uri에서 내 프로젝트명을 뺀 /*.me만 들고다니면됨
System.out.println("리퀘스트uri: "+requestURI); ///Model2JSP7/*.me
System.out.println("리퀘스트url: "+requestURL); //http://localhost:8088/Model2JSP7/*.me
//contextPath는 프로젝트명을 호출함
String contextPath = req.getContextPath();
System.out.println("contextPath: "+contextPath); ///Model2JSP7
//가상주소 command : 필요한 주소인 /*.me만 가져다니기 위해 substring()사용
String command = requestURI.substring(contextPath.length());
System.out.println("잘 짤렸는지 가상주소 command: "+command);


//9-1. 일회성이 아닌 다회용 여러번 쓸수있게 처리
Action action = null;

//6-3.ActionForward 객체사용
ActionForward forward = null;

//5. 특정 주소에 대한 처리
if(command.equals("/MemberJoin.me")){
System.out.println("/MemberJoin.me 호출");

//6. 회원가입처리 -> 회원정보 입력창(view의 개념이 필요)
//모델2에서 페이지 이동은 무조건 ActionForward사용
/*//6-1.페이지이동방법은 2가지 중 첫번째 : response
resp.sendRedirect("./member/insertForm.jsp");
//6-2.페이지이동방법은 2가지 중 두번째 : forward
RequestDispatcher dis = req.getRequestDispatcher("./member/insertForm.jsp");
dis.forward(req, resp);*/

//6-4. 특정주소에 대한 처리 후 페이지이동 =>먼저 특정주소에 대한 처리는 ActionForward 객체 사용
//ActionForward 객체 생성되기 전에는 null (값이 없다)이다가 객체생성후 이동정보가 생긴다
forward = new ActionForward();
// 이동할 주소
forward.setPath("./member/insertForm.jsp");
// 이동할 방법
forward.setRedirect(false);

//8.MemberJoinAction일때도 주소 출력
//8-1.Action페이지는 모델1의 pro페이지 역할을 한다.
}else if(command.equals("/MemberJoinAction.me")){ //주소에 `.`붙이면 안됨
System.out.println("/MemberJoinAction.me 주소 호출");

//8-2.전달되는 정보를 Action.java 인터페이스에 저장 --Acttion.java인터페이스와 MemberJoinAction.java생성--> DB로 전달
//Action페이지를 통해서 처리 => MemberJoinAction 객체를 생성 후 execute메서드 호출
//MemberJoinAction action = new MemberJoinAction(); //데이터 업캐스팅(Action <- MemberJoinAction)해서 저장

//9-2.`MemberJoinAction action = new MemberJoinAction()`을 `action = new MemberJoinAction();`으로 변경
action = new MemberJoinAction();

try {
System.out.println("@@@@ Controller : MemberJoinAction 객체생성완료 후 excute()호출완료");
forward = action.execute(req, resp);
System.out.println("@@@@ Controller : 처리완료 후 페이지 이동"+forward);
} catch (Exception e) {
e.printStackTrace();
}
}

//7.페이지이동 : 두가지방식
//이동정보가 있을때 (ActionForward객체가 생성되었을때) 페이지이동이 실행되어야한다
//7-1.response => true일때 이동
//7-2.forward => false일때 이동
if(forward != null){
System.out.println("@@@페이지이동@@@");
if(forward.isRedirect()){//1 - response.sendRedirect(주소)사용
//정보는 ActionForward객체 안에 있다
System.out.println("sendRedirect방식의 이동"+forward.getPath());
resp.sendRedirect(forward.getPath());
}else{ //0 - forward사용
System.out.println("RequestDispatcher방식의 이동"+forward.getPath());
RequestDispatcher dis = req.getRequestDispatcher(forward.getPath());
dis.forward(req, resp);
}
}
}//end of doProcess




DB 테이블 생성

  • 회원정보시 필요한 데이터를 입력받은 DB 테이블을 생성한다




insertForm.jsp 생성

  • DB테이블을 기준으로 입력받은 폼을 작성한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- .me가 가상경로이기때문에 ../style.css가 아닌 ./style.css(./의 의미는 루트)가 되어야한다  -->
<link href="./style.css" rel="stylesheet" />

<%
//1. DB생성 - member테이블 사용
//2. 데이터 입력받을 화면 작성
%>
<fieldset>
<legend>회원가입</legend>
<form action="./MemberJoinAction.me" method="post" name="fr">
아이디 <input type="text" name="id" required><br>
비밀번호 <input type="password" name="pw"><br>
이름 <input type="text" name="name"><br>
나이 <input type="text" name="age"><br>
성별
<input type="radio" name="gender" value="여"> 여성
<input type="radio" name="gender" value="남"> 남성<br>
이메일 <input type="text" name="email"><br>
<input type="submit" value="회원가입하기">
</form>
</fieldset>




인터페이스 Action.java 생성

  • 왜 Interface를 사용해야할까? SOLID 객체지향 설계
  • 추상메서드는 서브클래스들한테 강제성을 부여 => 틀이 정해짐 => 개발 형식의 통일.
    • 강제성 : implement를 하려면 내가 가지고 있는 추상메서드를 오버라이딩해야만 해!
  • 객체간의 관계가 약화됨 => 각각의 객체가 해당 동작만 처리/제어
    • 장점 : 오류처리에 용이. 오류나면 전체가 아닌 특정 객체 부분만 바꾸면 됨.
  • Action 페이지의 동작을 미리 선언해서 사용함.
1
2
3
4
5
6
7
8
9
10
11
package com.itwillbs.member.action;

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

public interface Action {
//상수, 추상메서드 사용가능
//1. 추상 메서드 작성
public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception;

}//end of interface




MemberJoinAction.java생성

  • Action으로 끝나면 모델1의 pro페이지의 역할을 한다.
  • 접두사 Action 객체는 항상 Action 인터페이스를 구현해서 사용
  • insertForm.jsp에서 회원가입을 클릭했을 때 MemberJoinAction.java로 이동되는 것을 구현.
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
public class MemberJoinAction implements Action {

@Override
public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
System.out.println("MemberJoinAction안의 execute() 실행됨");
//1. 한글처리
req.setCharacterEncoding("UTF-8");

//2.전달되는 파라미터 정보저장 ->MemberBean 생성
MemberBean mb = new MemberBean();
mb.setAge(Integer.parseInt(req.getParameter("age")));
mb.setEmail(req.getParameter("email"));
mb.setGender(req.getParameter("gender"));
mb.setId(req.getParameter("id"));
mb.setName(req.getParameter("name"));
mb.setPw(req.getParameter("pw"));
//시간은 파라미커가 아닌 현재시간으로 객체생성하여 저장
mb.setReg_date(new Timestamp(System.currentTimeMillis()));
System.out.println("@@@@ Action : 전달받은 정보 MemberBean 객체 확인"+mb);

//3. DB객체처리
MemberDAO mdao = new MemberDAO();
mdao.insertMember(mb);
System.out.println("@@@@ Action : 디비작업처리완료");

//4. 페이지이동 : 무조건 Controller로 이동
System.out.println("@@@@ Action : 페이지이동");
ActionForward forward = new ActionForward();
forward.setPath("./MemberLogin.me");
forward.setRedirect(true);
return forward;
}
}




MemberBean.java 생성

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
public class MemberBean {
//자바빈 -> 회원정보를 저장해서 이동시키기 위한 객체
//DTO(데이터 전송 객체)로도 불린다.

//1. DB의 테이블의 컬럼을 자바빈의 멤버 변수로 생성
private String id;
private String pw;
private String name;
private int age;
private String gender;
private String email;
private Timestamp reg_date; //import필수

//2. getter 와 setter생성
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPw() {
return pw;
(중략)

//3. toString생성
@Override
public String toString() {
return "멤버 [id=" + id + ", pw=" + pw + ", name=" + name + ", age=" + age + ", gender=" + gender + ", email="
+ email + ", reg_date=" + reg_date + "]";
}
}




라이브러리 8개 추가

  • WEB-INF폴더안에 lib폴더안에 8개 라이브러리 추가
  1. commons-collections4-4.4.jar
  2. commons-dbcp2-2.7.0.jar
  3. commons-pool2-2.8.0.jar
  4. cos.jar
  5. mysql-connector-java-5.1.49-bin.jar
  6. taglibs-standard-impl-1.2.5.jar
  7. taglibs-standard-jstlel-1.2.5.jar
  8. taglibs-standard-spec-1.2.5.jar




META-INF폴더안의 Context.xml 추가

  • 새로운 프로젝트나 추가 프로젝트를 진행하면 name, url, username, password 변경해줘야함
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
<?xml version="1.0" encoding="UTF-8"?>
<!-- 디비연결에 필요한 정보 저장 -->
<!--
속성
name : 외부에서 해당 정보에 접근할수있도록하는 이름값(변경가능)
auth : 자원관리자를 지정(Container/Application)
type : 웹에서 사용될때(name으로 호출) 표시되는 객체 타입
driverClassName : JDBC 드라이버 주소(mysql) (변경가능)
ORACLE : oracle.jdbc.driver.OracleDriver
url : 디비가 존제하는 위치 (디비서버의 주소) (변경가능)
ORACLE : jdbc:oracle:thin:@localhost:1521:orcl
username/password : 디비 접속 계정

maxWait : 커넥션풀에 사용가능한 커넥션이 없을경우 커넥션의 회수를 기다리는 시간지정
( 1 / 1000 초 사용)

-->

<Context>
<Resource
name="jdbc/model2DB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jspdb"
username="root"
password="1234"
/>
</Context>




MemberDAO.java 생성

  • DB연결 메서드 구현
  • 자원해제 메서드 구현
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
public class MemberDAO {
Connection con =null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "";

//1. DB연결메서드
public Connection getCon() throws Exception{
Context init= new InitialContext();
DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/model2DB"); //Context.xml의 주소와 동일해야함
con = ds.getConnection();
return con;
}//end of getCon()


//2. 자원해제 메서드 구현
public void closeDB(){
try{
if(rs != null) rs.close();
if(pstmt != null) pstmt.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}//closeDB()

//3. 회원가입처리 (외부에서 접근가능해야하니까 public)
public void insertMember(MemberBean mb){ //파라미터로 정보를 받아서 DB에 저장
try {
//3-1. DB연결메서드 불러오기
con = getCon();
//3-2. SQL & pstmt 생성 & 실행
sql = "insert into itwill_member value(?,?,?,?,?,?,?)";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, mb.getId());
pstmt.setString(2, mb.getPw());
pstmt.setString(3, mb.getName());
pstmt.setInt(4, mb.getAge());
pstmt.setString(5, mb.getGender());
pstmt.setString(6, mb.getEmail());
pstmt.setTimestamp(7, mb.getReg_date());
//insertForm에는 reg_date를 입력하는 란이 없기에 mb에 따로 넣어줘야한다.
//즉, 파라미터로 전달되지 않는 정보는 insertForm에서 직접생성
pstmt.executeUpdate();
System.out.println("회원가입성공");
} catch (SQLException e) {
System.out.println("sql구문땜시 회원가입실패");
e.printStackTrace();
} catch (Exception e) {
System.out.println("회원가입실패");
e.printStackTrace();
} finally {
//자원해제로 DB 효율성을 높일수있다.
closeDB();
}
}//insertMember닫힘

}//end of class




순서 정리

  • web.xml > index.jsp > 가상주소 MemberJoin.me(실제주소: insertForm.jsp) > 가상주소 MemberLogin.me(실제주소 : )
  • 가상주소 사용을 해주는 동작 : MemberFrontController