예습
ORM(Object Relational Mapping) 프레임 워크
- 기존 SQL 문만 따로 xml 로 뺀다
- 라이브러리가 지원된다
- 테이블의 컬럼명과 DTO 클래스의 필드명이 같은 이름이면 매핑이 바로 일어나게 한다
세션
- 세션값이 공유되기 때문에 계속해서 id 와 passwd 를 get/post 로 넘기지 않아도 된다
DBCP 환경설정
- url 은 오라클이 설치된 곳의 ip 주소가 들어간다
DAO 클래스에서 들어가는 것
DAO 클래스 싱글톤
- 객체를 한번만 생성해서 공유하는 개념
- 한번 만들어진 static 은 프로그램 종료시까지 메모리에 상주함
- 공유를 하기위해 멤버변수를 static 으로 설정한다
커넥션을 가져오는 코드
Context init = new InitialContext();
DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/orcl");
conn = ds.getConnection();
- init.lookup() 메소드로 Resource 를 찾아서 커넥션을 구해온다
- 이 3줄이 DAO 클래스에 들어간다
회원관리 프로그램 : 파일별 기능 및 구조 설명
회원관리 프로그램 : 회원 가입 기능
- memberform.html 파일은 이미 있다, 폼과 유효성검사가 완성되어 있음
- memberform.html
<!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('post').value = data.zonecode;
document.getElementById('address').value = data.address;
}
}).open();
}
</script>
<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="member.js"></script>
</head>
<body>
<form method="post" action="member.jsp">
<table border=1 width=450 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">
</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 maxlength=4 id="tel1" name="tel1">-
<input type=text size=4 maxlength=4 id="tel2" name="tel2">-
<input type=text size=4 maxlength=4 id="tel3" name="tel3">-
</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 maxlength=4 id="phone2" name="phone2">-
<input type=text size=4 maxlength=4 id="phone3" name="phone3">
</td>
</tr>
<tr><td>우편번호</td>
<td><input type=text size=5 maxlength=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="공부">공부
<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 rows=5 cols=50 id="intro" name="intro"
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>
- form 태그 action 에서 member.jsp 로 넘어가도록 지정
- setProperty action tag 를 사용하기 위해 form 태그 요소의 name 값을 DTO 프로퍼티명과 일치시켜야한다
+ 테이블 안 컬럼명 = DTO 필드명 = form 태그 요소의 name 값, 이 3가지를 일치시켜야 편하다
- member.jsp 파일을 만들 것
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page import="member.MemberDAO"%>
<%
request.setCharacterEncoding("utf-8");
%>
<jsp:useBean id="member" class="member.MemberDTO"/>
<jsp:setProperty property="*" name="member"/>
<%
String[] hobby = request.getParameterValues("hobby");
String h = ""; // h = "공부-게임-등산-"
for(String h1 : hobby) {
h += h1 + "-";
}
member.setHobby(h);
// DAO 객체 생성
MemberDAO dao = MemberDAO.getInstance();
int result = dao.insert(member); //insert SQL문을 실행할 메소드 호출
if(result == 1) { // 회원가입 성공
%>
<script>
alert("회원가입 성공");
location.href="loginform.html";
</script>
<% } else{ // 회원가입 실패 %>
<script>
alert("회원가입 실패");
history.go(-1);
</script>
<% }%>
0. 화면 출력을 할때만 HTML 코드가 필요하다, 여기선 출력을 하지 않으므로 위의 2줄 제외하고 HTML 코드를 지운다
1. memberform.html 에서 한글값이 post 로 넘어오므로 한글 인코딩
2. 폼에서 넘어온 값을 DTO 객체에 저장해야하므로 DTO 객체를 생성하고 각 프로퍼티에 값 저장
- useBean action tag 의 class 속성에는 패키지부터 시작해서 클래스까지 적어줌
- setProperty action tag 의 property 속성에는 "*", id 속성에는 객체명을 써야하므로 member 를 쓴다
- DTO 객체에 저장 = 폼에서 넘어온 값을 힙메모리상에 저장
예외 : 취미 부분 조작
- 취미의 name 값은 hobby 이고 value 는 공부, 게임 등인데 여러개를 선택했을때 테이블의 hobby 에 저장해야한다
- 선택했던 취미를 테이블쪽 hobby 라는 컬럼에 저장할때 "- " (하이픈) 으로 연결해서 저장한다
- 나중에 수정하는 화면에서 내가 가입시 선택했던 취미를 체크해서 나타나게 할 것
- 그러기 위해선 이 값들을 구분기호로 구분해서 저장해야한다, 나중에 split() 을 하려면 구분기호 사용해야함
1) 값을 getParamterValues() 로 직접받아서 String 형 배열 hobby 에 저장한다
2) 그 배열에 저장된 값을 - 로 연결해서 h 변수에 누적한다 ex) h = "공부-게임-등산-"
3) DTO 객체 member 에 setHobby() setter 메소드로 직접 hobby 프로퍼티 값을 설정
3. DAO 객체 생성
- 메모리상에 저장된 데이터를 member 테이블에 insert 하기 위해서 DAO 클래스에 메소드를 만들어야한다
- 이 메소드를 이 파일 member.jsp 에서 호출해야하므로 DAO 객체를 먼저 만들어야함
- 정적메소드로 DAO 객체 리턴받음
4. insert SQL 문을 실행할 메소드 호출
- DAO 클래스의 insert() 라는 회원 정보를 DB 에 저장해주는 메소드를 실행 후 삽입 개수를 리턴받음
- 매개변수로는 폼에서 넘어온 값을 저장한 DTO 객체 member 를 넘김
- 값의 주소값을 저장한 객체 member 를 넘기는 것이므로 Call By Reference 이다
5. 가입 성공, 가입 실패 처리
- 리턴된 값 result 가 1이면 회원가입 성공, 아니면 회원 가입 실패
- 성공시 로그인 폼으로, 실패시 이전 페이지로 이동
DAO 클래스 가입 기능 작성
- DAO 클래스에서 insert() 메소드를 작성해야한다
- MemberDAO.java
// DAO (Data Access Object)
package member;
import java.sql.Connection;
import java.sql.PreparedStatement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class MemberDAO {
// 싱글톤 : 객체 생성을 한번만 수행하는 것
private static MemberDAO instance = new MemberDAO();
public static MemberDAO getInstance() { // 정적 메소드
return instance;
}
// 커넥션들에서 커넥션을 구해오는 메소드
private Connection getConnection() throws Exception {
Context init = new InitialContext();
DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/orcl");
return ds.getConnection();
}
// 회원 가입
public int insert(MemberDTO member) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConnection(); // 커넥션풀에서 커넥션을 구해온다
String sql = "insert into member ";
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;
}
}
<insert() 메소드 형식 작성>
- JSP 파일에서 이 DAO 로 접근하므로 public 이어야한다
- 매개변수로 넘어온 DTO 객체에 저장된 값을 DB 의 테이블에 삽입할 것이므로 매개변수 자료형은 DTO
- int 를 자료형으로 해서 삽입된 데이터 개수를 반환하도록 하자, void 여도 된다
<insert() 메소드 내용 작성>
1. Connection, PreparedStatement 객체를 try-catch문 위에 작성해서 try 뿐 아니라 finally 에서도 사용가능하도록 함
2. 커넥션 풀을 통해서 커넥션을 구해오는 코드는 같은 DAO 클래스 내 getConnection() 메소드에 있으므로 try 내에서 호출
- JDBC 방식이 아닌 DBCP 방식으로 DB 접속하는 방법
- getConnection() 으로 커넥션을 구해서 Connection 객체인 con 에 저장했다
+ 같은 클래스의 메소드이므로 메소드명만 작성
+ getConnection() 메소드에서 예외를 throws 로 던지므로 여기서 예외처리 try-catch 를 해야한다
3. insert 하는 SQL문을 작성하면서 테이블의컬럼수에 맞게 ? 를 18개, 마지막은 sysdate 로 가입한 날짜 등록
4. sql문을 읽어와서 Connection 객체 con 을 통해 PreparedStatement 객체 생성
5. 모두 varchar2 이므로 setString() 으로 ? 에 값 설정, 값은 전달받은 member 객체에서 getter 메소드로 값을 가져옴
6. insert sql 문을 executeUpdate() 로 실행하고, 결과는 result 변수로 받음
- insert 가 잘실행되면 1 이 리턴되고, 예외가 발생시 초기에 설정해둔 값인 0 이 result 값이다
7. finally 에서 PreparedStatemet 객체 pstmt 를 닫고 Connection 객체 con 을 닫기
+ DAO 클래스에 가입기능 구현 완료, 나머지 기능을 추가할 것
- 회원 가입이 잘 실행되는지 확인
- 회원가입을 성공하고 로그인 페이지로 가고 있다
- 오라클 테이블에서 삽입 확인
- 테이블을 봐서 회원가입 insert 가 잘 구현되었음을 확인 가능
회원관리 프로그램 : ID 중복검사 (동기적, 팝업창)
- ID 중복검사 두가지 방법으로 구현할 것
1. 동기적인 방식으로 팝업창을 띄워서 ID 중복검사
2. 비동기적인 방식으로 팝업창을 띄우지 않고 바로 아래에 '사용중인 아이디입니다' 메세지 뿌리기
1. 동기적인 방식으로 팝업창을 띄워서 ID 중복검사
+ id 보기 (memberform.html 부분)
- memberform.html 의 js 파일인 member.js 파일 중 중복검사 부분을 보자
- 팝업창을 띄워서 처리하는 부분이다
- id 로 태그를 구해와서 click() 이벤트로 처리하고 있다
- id값을 입력하지 않았을때는 유효성 검사를 하고, id 를 입력했을때 팝업창을 띄워서 처리하고 있다
- 주소값에 idcheck.jsp 팝업창 파일을 적고, get 방식으로 id 값을 전달한다, $("#id").val() 로 사용자가 입력한 값을 전달
- 팝업창 idcheck.jsp 파일을 열고 있다
- idcheck.jsp 파일을 보자
- 현재는 출력만 하고 있다
- 이젠 단순 출력이 아닌 DB 에서 중복된 ID 가 있는지 검색하는 메소드를 호출할 것
- idcheck.jsp 파일 작성
<%@page import="member.MemberDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String id = request.getParameter("id");
MemberDAO dao = MemberDAO.getInstance();
// id 중복검사 메소드 호출
int result = dao.memberAuth(id);
if(result == 1) { // 중복 ID : 1
%>
<%=id %> 는 중복 ID 입니다. <br><br><br>
<input type="button" value="닫기">
<% } else{ // 사용가능한 ID : -1 %>
<%=id %> 는 사용가능한 ID 입니다.
<input type="button" value="닫기">
<% } %>
- DAO 에 중복된 ID 가 있는지 검색하는 memberAuth() 메소드를 만들고 그걸 이 idcheck.jsp 에서 호출할것
- 호출시 폼에서 넘겨받은 id 를 매개변수로 전달해야한다
- 그러기 위해 id 값을 받아서 변수로 저장하고 DAO 객체를 생성
- 사용가능한 ID 인지 사용중인 ID 인지 검색해서 결과를 int 형 변수 result 에 받을 것이다
- 메소드에서 검색 후 사용가능 한 ID 는 -1 를 돌려주기로 임의로 정하고, 중복 ID 는 1 을 돌려주기로 하자
DAO 클래스 ID 중복검사 기능 작성 : 동기적 처리 (팝업창)
- DAO 클래스에서 memberAuth() 메소드를 작성해야한다
- MemberDAO.java (추가)
// DAO (Data Access Object)
package member;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class MemberDAO {
// 싱글톤 : 객체 생성을 한번만 수행하는 것
private static MemberDAO instance = new MemberDAO();
public static MemberDAO getInstance() { // 정적 메소드
return instance;
}
// 커넥션들에서 커넥션을 구해오는 메소드
private Connection getConnection() throws Exception {
Context init = new InitialContext();
DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/orcl");
return ds.getConnection();
}
// ID 중복 검사
public int memberAuth(String id) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection(); // 커넥션 풀에서 커넥션을 구해옴
String sql = "select * from member where id=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, id);
rs = pstmt.executeQuery(); // SQL문 실행
if(rs.next()) { // 조건식을 만족하는 데이터를 구해옴
result = 1;
}
} catch(Exception e) {
} 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;
}
// 회원 가입
public int insert(MemberDTO member) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConnection(); // 커넥션풀에서 커넥션을 구해온다
String sql = "insert into member ";
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;
}
}
<memberAuth() 메소드 형식 작성>
- 아이디가 중복인지 아닌지 int 형으로 돌려주므로 리턴 자료형은 int
- 아이디가 중복인지 DB 에서 검색해야하므로 매개변수로 아이디를 받아야한다
<memberAuth() 메소드 내용 작성>
1. Connection, PreparedStatement, ResultSet 객체 생성
- DB 에서 Select 를 해서 중복아이디가 있는지 검색하는 것이므로 결과를 받을 ResultSet 객체를 만들어야함
2. try-catch-finally 문을 만들고 try 안에서 getConnection() 으로 커넥션 풀에서 커넥션을 구해옴
3. select SQL 문을 작성하며 where 조건절에 기본키인 id 컬럼을 쓰고, 매개변수로 넘어온 id 를 넣음
4. Connection 객체 con 으로 작성한 SQL 문을 읽어서 PreparedStatement 객체 생성
5. id 를 ? 에 설정하고 sql 문을 executeQuery() 메소드로 sql문을 실행하고 결과를 ResultSet 객체인 rs 로 받음
- select 문은 ResultSet 객체에 검색결과를 받는다
6. 검색된 데이터는 1 개이므로 if 문으로 rs.next() 를 통해 데이터를 가져왔는지만(=검색되는지만) 판별
- rs.next() 는 잘 가져오면 true 반환
- DB 에 검색 결과가 있는지만 확인하면 되므로 데이터를 가져왔는지만 판별하면 됨, 데이터를 꺼내지 않아도 됨
7. 잘 가져오면 result 를 1 로 설정하고, 잘 가져오지 못하면 result 를 -1 로 설정함
- 그럼 이미 사용중인 ID 가 DB에 있는 경우 result 는 1 이됨
8. ResultSet 객체, PreparedStatement 객체, Connection 객체 닫기
+ 다른 메소드 더 추가할 것, 아직 DAO 미완성
- 추가된 ID 중복검사 부분 코드만
추가 작업
1. 팝업창의 '닫기' 를 눌렀을때 열려있는 팝업창을 닫기
2.. 중복 ID 인 경우 아이디 지우기
3. 사용가능한 ID 면 닫으면서 '비밀번호' 입력부분에 에 focus 들어가게 하기
- idcheck.jsp 파일을 보자
<%@page import="member.MemberDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(document).ready(function(){
$("#close1").click(function(){ // 중복 ID인 경우의 닫기 버튼 클릭
opener.$("#id").val("").focus();
window.close();
});
$("#close2").click(function(){ // 사용 가능한 ID인 경우의 닫기 버튼 클릭
opener.$("#passwd").focus();
window.close();
});
});
</script>
<%
String id = request.getParameter("id");
MemberDAO dao = MemberDAO.getInstance();
// id 중복검사 메소드 호출
int result = dao.memberAuth(id);
if(result == 1) { // 중복 ID : 1
%>
<%=id %> 는 중복 ID 입니다. <br><br><br>
<input type="button" value="닫기" id="close1">
<% } else{ // 사용가능한 ID : -1 %>
<%=id %> 는 사용가능한 ID 입니다.
<input type="button" value="닫기" id="close2">
<% } %>
1. 중복ID 인 경우, 사용가능한 ID 인 경우 에 각각 있는 버튼들의 id 값을 다르게 설정해서 구분
2. jQuery 라이브러리를 사용하기 위해 jQuery 라이브러리 불러오기
3. 그리고 <script> 태그 내에서 추가 작업 구현하기
- 중복 ID 인 경우 입력된 id 를 지우고, id 입력창이 포커스 후 팝업창 닫기
- 사용가능한 ID 인 경우 비밀번호 입력창에 포커스 후 팝업창 닫기
+ opener 는 부모 window 를 의미
+ opener 는 부모 window 의 id 입력창과 비번 입력창에 지우기, 포커스 등을 하기위해 사용
- 중복 아이디인 경우
- 사용가능한 아이디인 경우
회원관리 프로그램 : ID 중복검사 (비동기적, Ajax)
2. 비동기적인 방식으로 팝업창을 띄우지 않고 바로 아래에 '사용중인 아이디입니다' 메세지 뿌리기
- 우선 메세지가 나타날 영역을 만들기 위해 회원가입 폼에 div 태그를 추가해야한다
- 이후 외부 js 파일인 member.js 파일로 가서 팝업창으로 처리하는 부분을 주석으로 막기
- 아래에 ajax 로 ID 중복검사를 할 것
- 사용자가 ID 를 입력하지 않은 경우 if문에서 유효성 검사, ID 를 입력한 경우만 else 문에서 처리
- member.js 에 ajax 부분 추가
$(document).ready(function(){
// ajax로 ID 중복검사
$("#idcheck").click(function(){
if($("#id").val() == "") {
alert("ID를 입력하세요.");
$("#id").focus();
return false;
} else {
var id = $("#id").val(); // 사용자가 입력한 ID
$.ajax({
type : "post", // get, post, put, delete
url : "idcheck1.jsp",
data : {"id" : id}, // json
success : function(data) { // callback 함수로 결과를 돌려받음
alert(data);
if(data == 1) { // 중복 ID
$("#myid").html("<font color=red>중복 ID입니다.</font>");
$("#id").val("").focus();
} else { // 사용 가능한 ID
$("#myid").html("<font color=red>사용 가능한 ID입니다.</font>");
$("#passwd").val("").focus();
}
}
}); // $.ajax() end
} // else end
}); // click end
});
- 사용자가 입력한 ID 값을 변수로 받아서 JSON 형태로 저장할 것
- ajax() 함수 사용해서 속성:속성값 형태로 옵션 적기
- post 로 전송하며, 요청할 파일명은 idcheck1.jsp 로 한다, 이후 idcheck1.jsp 파일을 생성할 것
+ type 옵션 중 get post 외에도 put, delete 도 있다, put 은 수정할때 요청하는 형식, delete 는 삭제할때 사용
- 사용자가 입력한 id 값을 전달해야하므로, data 옵션에서 전달되는 값의 형태는 json 형태로 작성
- 키와 밸류를 {"id" : id} 로 작성한다, 나중에 idcheck1.jsp 에서 request.getParameter("id") 로 값을 받을 수 있음
+ 두개 이상의 값을 전달할 때는 , 로 연결함
- success 다음의 내용은 결과를 잘 돌려받았을때만 실행됨, 이 function 은 콜백함수이고 data 로 값을 돌려받음
- 이 콜백함수로 리턴받는 결과는 idcheck1.jsp 에서 브라우저에 출력되는 값
- 중복 ID 는 1 을, -사용가능한 ID 는 - 1 받을 것임
- 1을 받으면 사용가능하다는 메세지를 div 태그에 뿌려줌, -1 을 받으면 사용불가능하다는 메세지를 div 에 뿌려줌
- 그럼 이제 idcheck1.jsp 에서 ID 중복검사 해주는 DAO 의 메소드를 호출해야함 (동기적 처리할때 구현해뒀던 메소드)
- 먼저 idcheck1.jsp 파일 생성 후 작성
<%@page import="member.MemberDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String id = request.getParameter("id");
System.out.println("id = " + id);
MemberDAO dao = MemberDAO.getInstance();
int result = dao.memberAuth(id);
System.out.println("result = " + result);
// result : 1 (중복 ID)
// result : -1 (사용 가능한 ID)
// 웹브라우저에 출력되는 값이 callback 함수로 리턴된다.
out.println(result);
%>
- member.js 에서 ajax() json 으로 전송한 id 값을 request.getParameter() 로 받는다
- 키값을 통해서 밸류를 구해온다
- 값이 제대로 왔는지 한번 콘솔창에 출력해보는 것이 좋다,
- 이때 이건 콘솔창에서만 출력되고 브라우저 출력이 아니므로 ajax() 로 요청한 곳에 돌려주는 값이 아님
- DAO 클래스 안의 memberAuth() 메소드를 사용하기 위해 DAO 객체 생성 후 memberAuth(id) 호출한 후 리턴값을 받음
- ajax() 에 돌려주고 싶은 값은 브라우저에 출력하면 된다 (out 객체 또는 표현식 태그로 출력)
+ member.js 에서 1을 받으면 중복ID 라는 표시를 div 태그에 띄움
- 이제 memberform.html 을 실행 후 ID 중복검사를 실행해보자
+ 크롬은 히스토리 기능때문에 바로 반영이 되지 않음
- 히스토리 삭제 후 실행
- 결과 캡처
- 중복 ID 입력시
- 사용가능한 ID 입력시
회원관리 프로그램 : 로그인 기능
- 폼인 loginform.html 에서 넘어온 아이디와 비밀번호를 login.jsp 가 받을 것
- loginform.jsp 파일 대신 loginform.html 파일 사용
- loginform.html 파일을 먼저 보자
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="login.js"></script>
</head>
<body>
<form method="post" action="login.jsp">
<table border=1 width=350 align=center>
<caption>로그인</caption>
<tr>
<td>ID</td>
<td><input type=text size=30 autofocus="autofocus" name="id" id="id"></td>
</tr>
<tr>
<td>비밀번호</td>
<td><input type=password size=30 name="passwd" id="passwd"></td>
</tr>
<tr>
<td colspan=2 align=center>
<!-- <button>Login</button> --> <!-- 전송기능 버튼 -->
<!-- <button type=submit>Login</button> --><!-- 전송기능 버튼 -->
<!-- <button type=button>Login</button> --> <!-- 버튼 -->
<!-- <input type=button value="login"> --> <!-- 버튼 -->
<input type=submit value="로그인"> <!-- 전송기능 버튼 -->
<input type=reset value="취소"> <!-- 초기화 버튼 -->
</td>
</tr>
</table>
</form>
</body>
</html>
- form 을 통해 login.jsp 로 로그인폼에 입력한 아이디와 비밀번호를 전달
- login.jsp 파일은 이전에 만들었고, 단순히 전달받은 아이디와 비밀번호를 출력만 했다
- 1, 2라인 제외 지우고 이제 action tag 들을 사용해서 DTO 객체를 만들고 id, passwd 값을 객체에 저장하자
- login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page import="member.MemberDAO"%>
<%
request.setCharacterEncoding("utf-8");
%>
<jsp:useBean id="member" class="member.MemberDTO"></jsp:useBean>
<jsp:setProperty property="*" name="member"/>
<%
MemberDAO dao = MemberDAO.getInstance();
int result = dao.memberCheck(member); // 회원인증 처리
if(result == 1) { // 회원인증 성공
session.setAttribute("id", member.getId()); // 세션으로 공유 설정
%>
<script>
alert("로그인 성공");
location.href = "main.jsp";
</script>
<% } else { // 회원인증 실패 %>
<script>
alert("로그인 실패");
history.go(-1);
</script>
<% } %>
1. 한글값이 post 방식으로 넘어오므로 한글 인코딩
2. DTO 객체만들기 위해 useBean action tag 사용, 아이디, 비번을 객체에 저장하기 위해 setProperty action tag 사용
3. 회원 인증을 해줄 DAO 메소드 memberCheck() 호출해서 사용할것이므로 DAO 객체 생성, DTO 객체 전달
- 회원 인증 : 로그인 폼에 입력한 아이디 비번과, DB 의 아이디 비번이 같아야함
4. 그 메소드에서 인증에 성공시 1을 리턴하게 할것이므로, result 가 1 인경우 세션으로 id 값을 공유 설정함
- 경우는 2가지 뿐이다, <일치, 불일치> 그러므로 메소드에서 int형 으로 리턴하게한다
- 로그인에 성공시, 여기서부터 세션 시작된것
- 이제부터는 로그인 되어있는 동안 id 값을 넘기지 않아도 된다
5. 이후 로그인 성공/실패 메세지 등을 처리함
- 이제 DAO 클래스 안에 memberCheck() 메소드 생성
DAO 클래스 회원 인증 기능 작성 (로그인)
- DAO 클래스에서 memberCheck() 메소드를 작성해야한다
- MemberDAO.java (추가)
// DAO (Data Access Object)
package member;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class MemberDAO {
// 싱글톤 : 객체 생성을 한번만 수행하는 것
private static MemberDAO instance = new MemberDAO();
public static MemberDAO getInstance() { // 정적 메소드
return instance;
}
// 커넥션들에서 커넥션을 구해오는 메소드
private Connection getConnection() throws Exception {
Context init = new InitialContext();
DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/orcl");
return ds.getConnection();
}
// ID 중복 검사
public int memberAuth(String id) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection(); // 커넥션 풀에서 커넥션을 구해옴
String sql = "select * from member where id=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, id);
rs = pstmt.executeQuery(); // SQL문 실행
if(rs.next()) { // 조건식을 만족하는 데이터를 구해옴
result = 1;
}
} catch(Exception e) {
} 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;
}
// 회원 가입
public int insert(MemberDTO member) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConnection(); // 커넥션풀에서 커넥션을 구해온다
String sql = "insert into member ";
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;
}
// 로그인
public int memberCheck (MemberDTO member) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection(); // 커넥션풀에서 커넥션을 구해온다
String sql = "select * from member where id=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, member.getId());
rs = pstmt.executeQuery(); // SQL문 실행
if(rs.next()) { // ID 일치
if(rs.getString("passwd").equals(member.getPasswd())) {
result = 1; // ID, 비번 일치 (회원인증 성공)
} else {
result = -1; // 비번 불일치
}
} else { // ID 불일치
result = -2;
}
} 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;
}
}
- 추가된 회원 인증 부분만 코드
<memberCheck() 메소드 형식 작성>
- JSP 파일에서 이 DAO 로 접근하므로 public 이어야한다
- 매개변수로 넘어온 DTO 객체에 저장된 아이디와 비번 으로 DB 의 테이블에서 검색해야하므로 매개변수 자료형은 DTO
- int 를 리턴자료형으로 해서 일치인지 불일치인지만 반환하자
<memberCheck() 메소드 내용 작성>
1. Connection, PreparedStatement, ResultSet 객체를 try-catch문 위에 작성해서 try 와 finally 에서도 사용가능하도록 함
- select SQL 문을 사용하므로 ResultSet 객체가 있어야한다
2. 커넥션 풀을 통해서 커넥션을 구해오는 코드는 같은 DAO 클래스 내 getConnection() 메소드에 있으므로 try 내에서 호출
- getConnection() 으로 커넥션을 구해서 Connection 객체인 con 에 저장했다
+ 같은 클래스의 메소드이므로 메소드명만 작성
3. select 하는 SQL문을 작성하면서 매개변수로 넘어온 객체의 id 값을 where 절에 넣어서 검색을 한다
4. sql문을 읽어와서 Connection 객체 con 을 통해 PreparedStatement 객체 생성
5. varchar2 이므로 setString() 으로 ? 에 값 설정
6. select sql 문을 executeQuery() 로 실행하고, 결과는 result 변수로 받음
7. rs.next() 가 true 이면 값을 가져왔다는 의미이고, 즉 DB 에 있는 id 와 일치한다는 의미이므로 if문 안에서 비밀번호 비교
- 아이디 일치시 안에서 또 if-else문을 만들어서 DB 검색결과의 비밀번호와 사용자가 입력한 비밀번호가 일치하는지 확인
1) 아이디가 일치할때, 비번 일치시 result = 1 으로 설정, 비번 불일치시 result = -1 으로 설정
2) 아이디도 일치하지 않았을땐 result = -2 로 설정
- 여기선 구체적으로 result 값을 지정하지만 result = -1 , result = -2 코드는 없는게 좋음
- '아이디가 틀렸습니다' '비밀번호가 틀렸습니다' 알려주는 것은 보안상 좋지 못함, '잘못된 정보입니다' 라고 보통 알림
8. finally 에서 ResultSet 객체 rs 닫고, PreparedStatemet 객체 pstmt 를 닫고, Connection 객체 con 을 닫기
+ DAO 클래스에 회원 인증(로그인) 기능 구현 완료, 나머지 기능을 추가할 것
- loginform.html 파일 실행해서 로그인(회원인증) 잘 구현되었는지 확인
- 맞는 아이디, 비밀번호 입력시
- main.jsp 가 아직 없어서 에러
- 잘못된 아이디, 비번 입력시
세션 유무(로그인 성공 유무) 에 따라 다른 화면 보여주기
- 로그인 성공시 main.jsp 파일로 넘어간다
- login.jsp 에서 로그인 성공시 세션을 설정했으므로 id 를 넘겨받을 필요 없이 설정된 세션에서 id 값 가져오기
- main.jsp 에서는 세션값이 있냐 없냐에 따라 다른 화면을 보여주기
- 세션값이 있는 경우 정상 로그인으로 판단하여 회원탈퇴등의 메뉴 나타나게 만들고
- 세션값이 없는 경우 로그인, 회원가입 메뉴가 나타나도록 만들기
- main.jsp 를 생성하고 작성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String id = (String) session.getAttribute("id");
if(id != null) { // 세션이 있는 경우 (정상적인 로그인)
%>
<%=id %>님 환영합니다. <br><br><br>
<a href="updateform.jsp">정보수정</a> <br>
<a href="logout.jsp">로그아웃 </a> <br>
회원탈퇴 <br>
<% } else { // 세션이 없는 경우 %>
<a href="memberform.html">회원가입</a> <br>
<a href="loginform.html">로그인</a> <br>
<% } %>
- session.getAttribute("id") 로 세션을 구해온다
- getAttribute() 메소드는 리턴자료형이 Object 이므로 원래 값의 자료형이었던 String 으로 다운캐스팅해야함
- id 값이 null 이 아닌경우는 세션이 있는 경우, null 인 경우는 세션이 없는 경우이다, if-else 문 처리
- 로그인 전엔 세션이 없다.
- 세션 유무에 따라 다른 화면을 보여준다
- 틀린 비밀번호를 입력했을때는 memberCheck() 과 login.jsp 로 처리하는 것이고, 여기는 세션이 없다는 뜻으로, 로그인이 아예 되어있지 않은상태이다
ex) 로그인을 아직 시도하지 않았을때
- 회원가입, 로그인은 각각의 폼으로 a 태그 링크를 걸고, 나머지 정보수정, 로그아웃, 회원탈퇴는 나중에 기능 구현 후 링크를 걸 것
- main.jsp 를 그냥 실행시 세션값이 없으므로 회원가입, 로그인 이 뜬다
- loginform.jsp 에서 정상적으로 로그인 해야 정보수정, 로그아웃, 회원탈퇴 메뉴가 뜬다
회원관리 프로그램 : 로그아웃 기능
- 이제 로그아웃 기능을 구현하자
- 로그아웃 기능 구현은 이 두가지를 하면 됨
1. 세션 삭제 해서 연결 끊기
2. 로그아웃되었다는 메세지를 뿌리고, 로그인 페이지로 돌아가기
- logout.jsp 생성 후 작성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<% // 세션 삭제 : 서버와 클라이언트의 연결이 끊어짐
session.invalidate();
%>
<script>
alert("로그아웃");
location.href = "loginform.html";
</script>
1. invalidate() 로 강제로 연결을 끊음
- 세션 삭제 : 서버와 클라이언트의 연결이 끊김
- 브라우저를 닫지 않아도 연결이 끊긴다
2. 로그아웃 메세지 뿌리고 '확인' 누르면 로그인 폼으로 돌아가기
- 로그인 폼에서 로그인을 하고 메인으로 간 다음 로그아웃을 해보자
회원관리 프로그램 : 정보수정 기능
- 정보수정 기능을 구현하자
- 정보수정 기능 구현 전에 수정폼 부터 구현해야한다
- updateform.jsp 파일에서 시작
- updateform.jsp 파일을 생성하고 memberform.html 의 내용을 그대로 복붙
- updateform.jsp 파일의 1, 2 라인은 남겨놓고 나머지 내용은 memberform.html 을 그대로 넣자
- 실행시 이렇게 회원 가입폼과 같아진다
- 이 폼에서 회원의 기본정보 ID 를 채워지면 회원 정보 폼과 유사해짐
- updateform.jsp 파일로 넘어올때 아무 값도 넘어오지 않았다
- 세션값으로 id 를 구해오면 된다
- 다음으로 세션으로 구한 이 id 를 가지고 DB 와 연결해서 한 사람의 모든 상세정보를 구해와야함
- DAO 의 한사람의 상세 정보를 구하는 메소드를 호출할 것이므로 DAO 객체를 만들기
- 그리고 select sql 문을 사용하는 메소드이므로 리턴자료형으로 돌려받아야함, 여기선 한사람의 상세정보이므로 List 가 아닌 DTO 자료형으로 리턴받으면 됨
- 이제 DAO 클래스에서 메소드 getMember() 를 만들자
DAO 클래스 수정폼에서 회원 상세정보 구하기
- MemberDAO.java (추가)
// DAO (Data Access Object)
package member;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class MemberDAO {
// 싱글톤 : 객체 생성을 한번만 수행하는 것
private static MemberDAO instance = new MemberDAO();
public static MemberDAO getInstance() { // 정적 메소드
return instance;
}
// 커넥션들에서 커넥션을 구해오는 메소드
private Connection getConnection() throws Exception {
Context init = new InitialContext();
DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/orcl");
return ds.getConnection();
}
// ID 중복 검사
public int memberAuth(String id) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection(); // 커넥션 풀에서 커넥션을 구해옴
String sql = "select * from member where id=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, id);
rs = pstmt.executeQuery(); // SQL문 실행
if(rs.next()) { // 조건식을 만족하는 데이터를 구해옴
result = 1;
}
} catch(Exception e) {
} 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;
}
// 회원 가입
public int insert(MemberDTO member) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConnection(); // 커넥션풀에서 커넥션을 구해온다
String sql = "insert into member ";
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;
}
// 로그인
public int memberCheck (MemberDTO member) {
int result = 0;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection(); // 커넥션풀에서 커넥션을 구해온다
String sql = "select * from member where id=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, member.getId());
rs = pstmt.executeQuery(); // SQL문 실행
if(rs.next()) { // ID 일치
if(rs.getString("passwd").equals(member.getPasswd())) {
result = 1; // ID, 비번 일치 (회원인증 성공)
} else {
result = -1; // 비번 불일치
}
} else { // ID 불일치
result = -2;
}
} 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;
}
// 회원 수정폼 : 한 사람의 상세정보 구하기
public MemberDTO getMember(String id) {
MemberDTO member = new MemberDTO();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = getConnection(); // 커넥션풀에서 커넥션을 구해온다
String sql = "select * from member where id=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, id);
rs = pstmt.executeQuery(); // SQL문 실행
if(rs.next()) {
// member.id = "test"; // 접근 안됨(private 접근제어자)
member.setId(rs.getString("id"));
member.setPasswd(rs.getString("passwd"));
member.setName(rs.getString("name"));
member.setJumin1(rs.getString("jumin1"));
member.setJumin2(rs.getString("jumin2"));
member.setMailid(rs.getString("mailid"));
member.setDomain(rs.getString("domain"));
member.setTel1(rs.getString("tel1"));
member.setTel2(rs.getString("tel2"));
member.setTel3(rs.getString("tel3"));
member.setPhone1(rs.getString("phone1"));
member.setPhone2(rs.getString("phone2"));
member.setPhone3(rs.getString("phone3"));
member.setPost(rs.getString("post"));
member.setAddress(rs.getString("address"));
member.setGender(rs.getString("gender"));
member.setHobby(rs.getString("hobby"));
member.setIntro(rs.getString("intro"));
member.setRegister(rs.getTimestamp("register"));
}
} 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 member;
}
}
<getMember() 메소드 형식 작성>
- id 에 해당하는 1명의 상세정보를 구하는 것이므로 매개변수로 id 를 넘기고 DTO 클래스로 리턴한다
- 위에서 DTO 객체를 생성하고 거기에 내용을 담아서 반환해야함
<getMember() 메소드 내용 작성>
1. Connection, PreparedStatement, ResultSet 객체를 try-catch문 위에 작성해서 try 와 finally 에서도 사용가능하도록 함
- select SQL 문으로 1명 정보를 구해오므로 ResultSet 객체가 있어야한다
2. 커넥션 풀을 통해서 커넥션을 구해오는 코드는 같은 DAO 클래스 내 getConnection() 메소드에 있으므로 try 내에서 호출
- getConnection() 으로 커넥션을 구해서 Connection 객체인 con 에 저장했다
+ 같은 클래스의 메소드이므로 메소드명만 작성
3. select 하는 SQL문을 작성하면서 매개변수로 넘어온 id 를 where 절에 넣어서 해당하는 사람을 검색 한다
4. sql문을 읽어와서 Connection 객체 con 을 통해 PreparedStatement 객체 생성
5. id 컬럼은 varchar2 이므로 setString() 으로 ? 에 값 설정
6. select sql 문을 executeQuery() 로 실행하고, 결과는 result 변수로 받음
7. rs.next() 에서 가져온 데이터가 있으면, 그 데이터를 가져와서 DTO 객체 member의 프로퍼티들에 저장하기
- 데이터 1개이므로 if 문 사용
8. Setter 메소드로 DTO 객체 member 의 프로퍼티에 값들을 rs.getString(컬럼명) 으로 가져와서 저장
- member.id = XX 는 접근제어자가 private 이라서 안되므로 Setter 메소드로 값을 할당해야함
+ 나중에 MyBatis 등을 쓰면 setter 메소드 코드로 인해 길어진 코드를 줄일 수 있다
+ 이때 rs.getString('hobby") 는 하이픈으로 연결된 값
+ register 는 timestamp 형이므로 rs 에서 getTimestamp() 로 가져와야한다
9. finally 에서 ResultSet 객체 rs 닫고, PreparedStatemet 객체 pstmt 를 닫고, Connection 객체 con 을 닫기
+ DAO 클래스에 수정폼에서 회원 상세정보를 구해오는 기능 구현 완료, 나머지 기능을 추가할 것
- updateform.jsp (이어서)
- 상세정보를 구하는 DAO 클래스의 메소드 작성 후 다시 updateform.jsp 로 돌아와서 리턴받은 값을 화면에 뿌려주자
- 취미 같은 경우는 하이픈이 이어진 상태이므로 split() 으로 파싱하고 가공해서 체크표시가 되어있게끔 할것
- 먼저 리턴받은 DTO 객체인 member 에서 getHobby() 로 '공부-게임-' 같은 값을 가져온 후 - 로 파싱해서 String 배열인 h 에 저장
- form 태그의 action 값을 update.jsp 로 수정
+ 테이블 태그의 캡션값도 '회원 수정 폼' 으로 바꾸기
- 회원 수정폼이므로 ID 값은 수정하지 못하도록 입력양식을 지우고 출력만 시킴
- 그 다음 비밀번호가 맞는 경우만 수정할 수 있도록 비밀번호의 입력폼은 그대로 둠, value 설정 안함
- 성명 에는 성명이 출력되도록 value 속성으로 출력
- 비밀번호 제외하고 나머지도 성명과 같은 방식으로 value 값 설정
- updateform.jsp 부분 코드
예외
- textarea 는 value 속성이 없기때문에 textarea 태그 사이 내용에 설정해야만 내용이 textarea 에 나타남
1.휴대폰 번호 앞자리는 value 값 설정을 다른방식으로 해야한다
2. 라디오버튼인 성별 처리
3. 체크박스인 취미 처리
- 이 3가지를 수정폼에 나타나게 하는 처리가 복잡하다
1. 휴대폰 번호 앞자리 처리
- 양식은 select 이다
- 사용자가 가입시 010 을 선택했다면, 여기 수정폼에서 010 이 선택된 상태로 만들어야한다
- phone1 컬럼의 값 010 과 select 의 010 과 같으면 선택되도록 만듬
- phone1 컬럼의 값 011 과 select 의 011 이 같으면 선택되도록 만듬, ...
- select-option 에서 사용자의 휴대폰 앞자리번호와 같은지 if 문으로 확인
- 이런 방식으로 처리한다
+ <%="selected" %> 대신 그냥 selected 로 해도 된다,
+ <%="selected"%> 는 출력을 하는 거지만 option 태그 안에서 출력이므로 선택이 되는 것임
+ 그냥 selected 라고 해도 적히므로 그냥 selected 로 적어도 된다
- 010 뿐 아니라 나머지 휴대폰 앞자리도 마찬가지로 처리
2. 라디오버튼인 성별 처리
- 휴대폰 앞자리와 비슷하게 조건문을 써서 사용자가 가입시 입력한 성별과 일치하면 chekced
- 라디오버튼은 selected 대신 checked 되면 체크된 상태로 나타남
3. 체크박스인 취미 처리
- 앞의 휴대폰 앞자리와 라디오버튼처럼 일일히 조건문으로 검사하지 않고 jQuery 로 처리하면 간결하게 처리 가능
+ 취미는 가입시 2개이상 선택하도록 만들어졌다
- 취미를 위쪽에서 파싱해서 String 배열인 h 에 저장해뒀다
ex) h 배열의 취미를 하나씩 가져오는데 만약 '공부' 와 '게임' 이인 경우
- input 이 checkbox 인걸 구해오는데 name 이 hobby 인것 5개 중 value 값이 '공부' 인것만 구해와서 체크해라
- input 이 checkbox 인걸 구해오는데 name 이 hobby 인것 5개 중 value 값이 '게임' 인것만 구해와서 체크해라
- updateform.jsp 에 추가할 것들이 있다
- updateform.jsp 에서 id 가 넘어가지 않으므로 hidden 으로 넘겨주자
+ 넘겨야 update.jsp 에서 update 할때 id 로 update 를 할 수 있다 (지금은 update 가 아니라 업데이트폼을 하고 있다)
+ id를 세션으로 구해도 되지만 form 으로 전송하는 김에 한번에 전송
- updateform.jsp 전체 코드
<%@page import="member.MemberDAO"%>
<%@page import="member.MemberDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String id = (String) session.getAttribute("id");
MemberDAO dao = MemberDAO.getInstance();
// 한 사람의 상세정보 구해오기
MemberDTO member = dao.getMember(id);
// h[0]="공부", h[1]="게임", h[2]="등산"...
String[] h = member.getHobby().split("-");
%>
<!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('post').value = data.zonecode;
document.getElementById('address').value = data.address;
}
}).open();
}
</script>
<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="member.js"></script>
<script>
$(document).ready(function(){
<% for(String s : h) { %>
$("input:checkbox[name='hobby'][value='<%=s%>']").attr("checked",true);
<% } %>
});
</script>
</head>
<body>
<form method="post" action="update.jsp">
<input type="hidden" name="id" value="<%=member.getId() %>">
<table border=1 width=450 align="center">
<caption>회원 수정 폼</caption>
<tr><td>ID</td>
<td><%=member.getId() %></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" value="<%=member.getName()%>"></td>
</tr>
<tr><td>주민번호</td>
<td><input type=text size=6 maxlength=6 id="jumin1"
name="jumin1" value="<%=member.getJumin1()%>">-
<input type=text size=7 maxlength=7 id="jumin2"
name="jumin2" value="<%=member.getJumin2()%>">
</td>
</tr>
<tr><td>E-Mail</td>
<td><input type=text size=10 id="mailid"
name="mailid" value="<%=member.getId()%>">@
<input type=text size=10 id="domain"
name="domain" value="<%=member.getDomain()%>">
<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 maxlength=4 id="tel1"
name="tel1" value="<%=member.getTel1() %>">-
<input type=text size=4 maxlength=4 id="tel2"
name="tel2" value="<%=member.getTel2() %>">-
<input type=text size=4 maxlength=4 id="tel3"
name="tel3" value="<%=member.getTel3() %>">-
</td>
</tr>
<tr><td>핸드폰</td>
<td><select id="phone1" name="phone1">
<option value="">번호선택</option>
<option value="010"
<%if(member.getPhone1().equals("010")) { %>
<%="selected" %>
<%} %>>010</option>
<option value="011"
<%if(member.getPhone1().equals("011")) { %>
<%="selected" %>
<%} %>>011</option>
<option value="016"
<%if(member.getPhone1().equals("016")) { %>
<%="selected" %>
<%} %>>016</option>
<option value="018"
<%if(member.getPhone1().equals("018")) { %>
<%="selected" %>
<%} %>>018</option>
<option value="019"
<%if(member.getPhone1().equals("019")) { %>
<%="selected" %>
<%} %>>019</option>
</select>-
<input type=text size=4 maxlength=4 id="phone2"
name="phone2" value="<%=member.getPhone2()%>">-
<input type=text size=4 maxlength=4 id="phone3"
name="phone3" value="<%=member.getPhone3()%>">
</td>
</tr>
<tr><td>우편번호</td>
<td><input type=text size=5 maxlength=5 id="post"
name="post" value="<%=member.getPost()%>">
<input type=button value="우편검색" onClick="openDaumPostcode()">
</td>
</tr>
<tr><td>주소</td>
<td><input type=text size=45 id="address"
name="address" value="<%=member.getAddress()%>"></td>
</tr>
<tr><td>성별</td>
<td><input type=radio id="male" name="gender" value="남자"
<%if(member.getGender().equals("남자")){ %>
<%="checked" %>
<%} %>>남자
<input type=radio id="female" name="gender" value="여자"
<%if(member.getGender().equals("여자")){ %>
<%="checked" %>
<%} %>>여자
</td>
</tr>
<tr><td>취미</td>
<td><input type=checkbox id="h1" name="hobby" value="공부">공부
<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 rows=5 cols=50 id="intro" name="intro"
placeholder="자기소개를 100자 이내로 입력하세요"><%=member.getIntro() %></textarea>
</td>
</tr>
<tr><td colspan=2 align=center>
<input type=submit value="회원수정">
<input type=reset value="취소">
</td>
</tr>
</table>
</form>
</body>
</html>
- 로그인 폼에서 로그인 하고 '정보수정' 을 눌렀을때 나타나는 완성된 수정 폼 캡처