이제 내 홈페이지를 회원제로 바꿔 보려고 한다. 그럼 우선 DB에 멤버 목록을 만들어 줘야 한다.
그리고 캡처를 까먹었는데 시퀀스도 만들어 줘야 한다.
CREATE SEQUENCE member_seq
START WITH 1
INCREMENT BY 1
NOMAXVALUE;
회원 목록 페이지는 나중에 만든 거지만 시퀀스에 대해 설명하기 위해 일단 넣었다.
start with 부터 신경 안 쓰고 그냥 create로 sequence 만들었다가 위 사진처럼 41 27 25 이렇게 만들어졌다. 이러면 나중에 엉킬 가능성이 있으니까 설정은 빼먹지 말자.
NOMAXVALUE 는 최대값이 없이 쭉 생성하는 것이다.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ include file="top.jsp"%>
<!-- login.jsp-->
<link rel="stylesheet" type="text/css" href="style.css">
<br>
<div align="center">
<img src="img/bottom.gif" width=570 height="40" border="0" alt="">
<br>
<br>
<img src="img/tm_login.gif" width=100 height="13" border="0"
align=center ALT="회원 로그인">
</div>
<form name="f" action="login_ok.jsp" method="post">
<table width="60%" align="center" height="120">
<tr>
<td align="right" width="30%">
<img src="img/id01.gif"
width="28" height="11" border="0" alt="아이디">
</td>
<td width="40%">
<input type="text" name="id" tabindex="1">
</td>
<td rowspan="2" width="30%" valign="middle">
<a href="javascript:loginCheck()">
<img src="img/bt_login.gif" border="0" alt="로그인" tabindex="3"> <br>
</a>
<nobr>
<input type="checkbox" name="saveId">
<font face="굴림" size="2">아이디 기억하기</font>
</nobr>
</td>
</tr>
<tr>
<td align="right">
<img src="img/pwd.gif"
width="37" height="11" alt="비밀번호">
</td>
<td>
<input type="password" name="passwd" tabindex="2">
</td>
</tr>
<tr>
<td colspan="3" align="center">
<img src="img/bt_join.gif" width="60" height="22" alt="회원가입">
<img src="img/bt_search_id.gif" width="60" height="22" alt="아이디 찾기">
<img src="img/bt_search_pw.gif" width="60" height="22" alt="비밀번호 찾기">
</td>
</tr>
</table>
</form>
<%@ include file="bottom.jsp"%>
그리고 스타일 시트도 만들어 준다.
/*style.css
/*표준 글꼴 서식 스타일*/
h1,h2,h3,h4,h5,h6{
font-family:verdana;
color:navy;
}
body, td, input, select, textarea, p, th{
font-size:13px;
font-family:verdana;
color:navy;
padding:4px;
}
/*표준 링크 스타일*/
a:link{
color:#000000; text-decoration:none;
font-size:13px; font-family:verdana;
}
a:visited{
color:red; text-decoration:none;
font-size:13px; font-family:verdana;
}
a:hover{
color:orange; text-decoration:underline;
font-size:13px; font-family:verdana;
}
/*입력 양식 스타일 .은 class로 #은 id로*/
.box{
border:1px solid navy;
padding-left:8px;
}
.outline{
border-top:4px double navy;
border-bottom:4px double navy;
}
.m1{
background-color:#EAF0E8;
border-bottom:1px dotted #9933CC;
}
.m2{
background-color:#FFCC00;
border-bottom:1px dotted #9933CC;
}
.m3{
border-bottom:1px dotted navy;
}
회원 가입 페이지를 만드는 순서를 생각해 보자.
- 멤버 DTO와 DAO 생성
- DAO 에 멤버 리스트 확인하여 member에 회원 가입을 시도하는 이름과 주민번호 있는지 확인
- member 인지 check 할 것 : DB 확인 후 이름, 주민번호를 확인할 것. 회원 가입이 되어 있다면 가입 불가함
package my.member;
public class MemberDTO {
private int no;
private String name;
private String id;
private String passwd;
private String ssn1;
private String ssn2;
private String email;
private String hp1;
private String hp2;
private String hp3;
private String joindate;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getSsn1() {
return ssn1;
}
public void setSsn1(String ssn1) {
this.ssn1 = ssn1;
}
public String getSsn2() {
return ssn2;
}
public void setSsn2(String ssn2) {
this.ssn2 = ssn2;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getHp1() {
return hp1;
}
public void setHp1(String hp1) {
this.hp1 = hp1;
}
public String getHp2() {
return hp2;
}
public void setHp2(String hp2) {
this.hp2 = hp2;
}
public String getHp3() {
return hp3;
}
public void setHp3(String hp3) {
this.hp3 = hp3;
}
public String getJoindate() {
return joindate;
}
public void setJoindate(String joindate) {
this.joindate = joindate;
}
public String getAllhp() {
if (hp1 == null) return "전화 없음";
return hp1 + "-" + hp2 + "-" + hp3;
}
}
// 멤버 체크하기
public boolean checkMember(String name, String ssn1, String ssn2) throws SQLException{
try {
Connection con = DriverManager.getConnection(url, user, pass);
sql = "select name from member where ssn1 = ? and ssn2 = ?";
PreparedStatement ps = con.prepareStatement(sql); // sql 문의 결과를 가져옴
ps = con.prepareStatement(sql);
ps.setString(1, ssn1);
ps.setString(2, ssn2);
rs = ps.executeQuery(); // rs 쿼리 문의 결과를 담음
// 주민등록번호는 고유 값이므로 굳이 리스트를 만들어서 반환할 필요? : X
if (rs.next()) {
return true;
}
return false;
}finally {
if (rs != null) rs.close();
if (ps != null) ps.close();
if (con != null) con.close();
}
}
// 멤버 추가하기
public int insertMember(MemberDTO dto) throws SQLException {
try {
Connection con = DriverManager.getConnection(url, user, pass);
sql = "insert into member values(member_seq.nextval, ?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, dto.getName());
ps.setString(2, dto.getId());
ps.setString(3, dto.getPasswd());
ps.setString(4, dto.getSsn1());
ps.setString(5, dto.getSsn2());
ps.setString(6, dto.getEmail());
ps.setString(7, dto.getHp1());
ps.setString(8, dto.getHp2());
ps.setString(9, dto.getHp3());
int res = ps.executeUpdate();
return res;
}finally {
if (ps != null) ps.close();
if (con != null) con.close();
}
}
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!-- member_check.jsp -->
<jsp:useBean id="mbdao" class="my.member.MemberDAO" />
<%
request.setCharacterEncoding("EUC-KR");
String name = request.getParameter("name");
String ssn1 = request.getParameter("ssn1");
String ssn2 = request.getParameter("ssn2");
if (name == null || name.trim().equals("") ||
ssn1 == null || ssn1.trim().equals("") ||
ssn2 == null || ssn2.trim().equals("")){
response.sendRedirect("memberSsn.jsp");
return;
}
boolean isMember = mbdao.checkMember(name, ssn1, ssn2);
if (isMember){%>
<script type="text/javascript">
alert("기존 회원입니다. 로그인을 해 주세요.")
self.close()
</script>
<% }else {%>
<form name="f" action="member_input.jsp" method="post">
<input type="hidden" name="name" value="<%= name %>"/>
<input type="hidden" name="ssn1" value="<%= ssn1 %>"/>
<input type="hidden" name="ssn2" value="<%= ssn2 %>"/>
</form>
<script type="text/javascript">
alert("회원 가입 페이지로 이동합니다.")
document.f.submit()
</script>
<% } %>
멤버 보기를 통해 서버가 클라이언트의 계정을 관리하고, 수정할 수 있도록 처리해 줄 것이다.
그럼 우선 첫 번째로 DB에서 멤버 리스트를 긁어 오자.
// makeList 메서드를 통해 DTO 객체를 담아와 멤버 전체의 list 만들어 주기
public List<MemberDTO> makeList(ResultSet rs) throws SQLException{
List<MemberDTO> list = new ArrayList<>();
while(rs.next()) {
MemberDTO dto = new MemberDTO();
dto.setNo(rs.getInt("no"));
dto.setName(rs.getString("name"));
dto.setId(rs.getString("id"));
dto.setSsn1(rs.getString("ssn1"));
dto.setSsn2(rs.getString("ssn2"));
dto.setPasswd(rs.getString("passwd"));
dto.setEmail(rs.getString("email"));
dto.setHp1(rs.getString("hp1"));
dto.setHp2(rs.getString("hp2"));
dto.setHp3(rs.getString("hp3"));
dto.setJoindate(rs.getString("joindate"));
list.add(dto);
}
return list;
}
// 멤버 리스트 확인
public List<MemberDTO> listMember() throws SQLException{
try {
con = DriverManager.getConnection(url, user, pass);
String sql = "select * from member";
ps = con.prepareStatement(sql); // sql 문의 결과를 가져옴
ResultSet rs = ps.executeQuery(); // rs 쿼리 문의 결과를 담음
return makeList(rs);
}finally{
if (rs != null) rs.close();
if (ps != null) ps.close();
if (con != null) con.close();
}
}
두 메서드로 멤버 리스트를 만들고, 리스트를 확인할 수 있게 됐다.
이제 jsp 파일을 만들어 보자.
멤버 전체를 볼 수 있는 jsp 페이지.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR" import="java.util.*, my.member.*"%>
<!-- memberAll.jsp -->
<% request.setCharacterEncoding("EUC-KR"); %>
<jsp:useBean id="memdao" class="my.member.MemberDAO"/>
<%@ include file="../top.jsp"%>
<link rel="stylesheet" type="text/css" href="../style.css">
<div align="center">
<hr color="green" width="300">
<h2>회 원 목 록 페 이 지</h2>
<hr color="green" width="300">
<table borde="0" width="100%" class="outline">
<tr>
<th class="m1">번호</th>
<th class="m1">이름</th>
<th class="m1">아이디</th>
<th class="m1">이메일</th>
<th class="m1">전화번호</th>
<th class="m1">가입일</th>
<th class="m1">수정 | 삭제</th>
</tr>
<%
List<MemberDTO>list = memdao.listMember();
if (list == null || list.size() == 0){%>
<tr>
<td colspan="5">등록된 멤버가 없습니다.</td>
</tr>
<% }else{
for (MemberDTO dto : list){%>
<tr>
<td align="center"><%=dto.getNo()%></td>
<td align="center"><%=dto.getName()%></td>
<td align="center"><%=dto.getId()%></td>
<td align="center"><%=dto.getEmail()%></td>
<td align="center"><%=dto.getHp1() + "-" + dto.getHp2() + "-" + dto.getHp3()%></td>
<td align="center"><%=dto.getJoindate()%></td>
<td align="center">수정 | 삭제</td>
</tr>
<% }
}%>
</table>
</div>
리스트 보는 건 사실 student와 똑같이 만들면 된다.
그럼 이제 수정, 삭제할 수 있는 페이지도 만들어 보자.
삭제를 누르면 delete 페이지로 이동해 멤버를 삭제해 준다.
멤버 수정, 삭제에 a 태그를 걸어 delete, update.jsp로 움직일 수 있도록 링크를 걸어준다.
<td align="center"><%=dto.getJoindate()%></td>
<td align="center"><a href="member_update.jsp?no=<%=dto.getNo()%>">수정</a> | <a href="member_delete.jsp?no=<%=dto.getNo()%>">삭제</a></td>
정보를 같이 넘기기 위해 get 방식으로 no 데이터를 서버에게 전달했다.
? : 파라미터 값과 주소를 경계하는 값이다.
& : 파라미터 값과 파라미터 값을 경계하는 표시이다.
띄어쓰기는 하지 말 것
나는 get 방식을 사용할 때는 무조건 < form > 태그를 사용해야 한다고 생각했는데 < a > 태그를 통해서도 get 방식으로 데이터를 전달할 수 있다고 한다.
no는 그냥 순번이기 때문에 정보 유출될 일도 없고 편하고 간단한 방법을 배웠다고 생각한다.
public int deleteMember(int no) throws SQLException {
try {
con = DriverManager.getConnection(url, user, pass);
String sql = "delete from member where no = ?";
ps = con.prepareStatement(sql);
ps.setInt(1, no);
int res = ps.executeUpdate();
return res;
}finally {
if (ps != null) ps.close();
if (con != null) ps.close();
}
}
멤버 수정의 과정을 다시 머리속으로 그려봐야 한다.
1. 수정 버튼 누르기
2. 수정 화면으로 넘어감 아이디, 이름, 주민번호를 제외한 나머지 개인 정보를 수정할 수 있도록 설정
3. 유효성 검사 후 수정 ok jsp 로 넘어가 DB 업데이트
// no 를 넣어 주면 멤버의 DTO 를 꺼내주는 코드
// 어차피 하나니까 리스트의 0번을 return 해 주면 된다
public MemberDTO getMember(int no) throws SQLException {
try {
con = DriverManager.getConnection(url, user, pass);
String sql = "select * from member where no = ?";
ps = con.prepareStatement(sql);
ps.setInt(1, no);
rs = ps.executeQuery();
List<MemberDTO> list = makeList(rs);
return list.get(0);
}finally {
if (rs != null) rs.close();
if (ps != null) ps.close();
if (con != null) con.close();
}
}
// DB에 멤버를 업데이트 해 주는 코드
public int updateMember(MemberDTO dto) throws SQLException {
try {
Connection con = DriverManager.getConnection(url, user, pass);
sql = "update member set passwd=?, email=?, hp1=?, hp2=?, hp3=? where no = ?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, dto.getPasswd());
ps.setString(2, dto.getEmail());
ps.setString(3, dto.getHp1());
ps.setString(4, dto.getHp2());
ps.setString(5, dto.getHp3());
ps.setInt(6, dto.getNo());
int res = ps.executeUpdate();
return res;
}finally {
if (ps != null) ps.close();
if (con != null) con.close();
}
}
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR" import="java.sql.*, my.member.*"%>
<jsp:useBean id="memdao" class="my.member.MemberDAO"/>
<!-- member_update -->
<%
String no = request.getParameter("no");
//2. 받은 데이터 유효성 검사하기(데이터가 null이면 이전페이지로 이동시키자)
if (no == null || no.trim().equals("")){
response.sendRedirect("memberAll.jsp");
return;
}
MemberDTO dto = memdao.getMember(Integer.parseInt(no));
%>
<%@ include file="../top.jsp" %>
<link rel="stylesheet" type="text/css" href="../style.css">
<script type="text/javascript">
function check() {
if (f.id.value == "") {
alert("아이디를 입력해 주세요")
f.id.focus()
return
}
if (!f.passwd.value){
// 자바 스크립트는 값이 없다면 false로 넘어온다
alert("비밀번호를 입력해 주세요!!")
f.passwd.focus()
return
}
document.f.submit()
// 유효성 검사를 여기서 하고 다음 페이지로 넘기는 방법
}
</script>
<form name="f" method="POST" action="member_update_ok.jsp">
<input type="hidden" name="no" value="<%=no%>">
<table width="600" align="center" class="outline">
<tr>
<td colspan="2" align=center class="m2">회원 수정</td>
</tr>
<tr>
<td width="150" class="m3">이름</td>
<td class="m3">
<input type="text" name="name" class="box" value="<%=dto.getName()%>" disabled>
<input type="hidden" name="name" value="<%=dto.getName()%>"/>
<!-- disabled를 먹여 버리면 창이 죽으면서 클릭도 안 되지만 값 전송도 안 된다. 값은 따로 hidden으로 넘겨 주어야 한다. -->
</td>
</tr>
<tr>
<td width="150" class="m3">아이디</td>
<td class="m3">
<input type="text" name="id" class="box" value="<%=dto.getId()%>" readOnly>
</td>
</tr>
<tr>
<td width="150" class="m3">비밀번호</td>
<td class="m3">
<input type="password" name="passwd" class="box" value="<%=dto.getPasswd()%>">
</td>
</tr>
<tr>
<td width="150" class="m3">주민번호</td>
<td class="m3">
<input type="text" name="ssn1" class="box" value="<%=dto.getSsn1()%>" disabled> -
<input type="password" name="ssn2" class="box" value="<%=dto.getSsn2()%>" readOnly>
<!-- readOnly 가 더 간단한 방법이다. -->
</td>
</tr>
<tr>
<td width="150" class="m3">이메일</td>
<td class="m3">
<input type="text" name="email" class="box" value="<%=dto.getEmail()%>">
</td>
</tr>
<tr>
<td width="150" class="m3">연락처</td>
<td class="m3">
<input type="text" name="hp1" class="box" size="3" maxlength="3" value="<%=dto.getHp1()%>"> -
<input type="text" name="hp2" class="box" size="4" maxlength="4" value="<%=dto.getHp2()%>"> -
<input type="text" name="hp3" class="box" size="4" maxlength="4" value="<%=dto.getHp3()%>">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<a href="javascript:check()">[수정]</a>
<a href="#">[취소]</a>
</td>
</tr>
</table>
</form>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!-- member_input_ok.jsp -->
<% request.setCharacterEncoding("EUC-KR"); %>
<jsp:useBean id="memdao" class="my.member.MemberDAO"/>
<jsp:useBean id="memdto" class="my.member.MemberDTO"/>
<jsp:setProperty property="*" name="memdto"/>
<%
if (memdto.getName() == null || memdto.getName().trim().equals("")){
response.sendRedirect("memberSsn.jsp");
return;
}
int res = memdao.insertMember(memdto);
if (res > 0){%>
<script type="text/javascript">
alert("회원 가입 성공 : 로그인해 주세요")
self.close()
</script>
<% }else {%>
<script type="text/javascript">
alert("회원 가입 실패 : 다시 입력해 주세요")
location.href="memberSsn.jsp"
</script>
<% }
%>
이제 로그인 페이지에서 회원 id, passwd 찾기 기능을 구축해 보자.
우선 찾는 메서드를 만들어 본다.
중요한 점은 \
두 개가 비슷하니까 같은 코드 내에서 mode 를 자바 스크립트 내 주소값에 같이 보내 구분하는 것이다.
<script type="text/javascript">
function searchMember(mode){
window.open("<%=request.getContextPath()%>/login/searchMember.jsp?mode="+mode, "search", "width=640, height=400")
}
</script>
이건 멤버가 id나 password를 찾을 때 가게 하는 자바스크립트 함수인데, 함수에 mode 값을 줘서 jsp로 넘어갈 때 get 방식으로 mode 값이 같이 가게 해 줬다.
그럼 한 코드 내에서 id인지 password인지 구분할 수 있게 된다.
public String searchMember(String name, String ssn1, String ssn2, String id) throws SQLException {
try {
con = pool.getConnection();
String sql = null;
if (id == null) {
sql = "select id from member where "
+ "name=? and ssn1=? and ssn2=?";
}else {
sql = "select passwd from member where "
+ "name=? and ssn1=? and ssn2=? and id=?";
}
ps = con.prepareStatement(sql);
ps.setString(1, name);
ps.setString(2, ssn1);
ps.setString(3, ssn2);
if (id != null) {
ps.setString(4, id);
}
rs = ps.executeQuery();
if (rs.next()) {
String msg = rs.getString(1);
return msg;
}else {
return "정확한 값을 입력해야 아이디 또는 비밀번호를 알 수 있습니다.";
}
}finally {
if (rs != null) rs.close();
if (ps != null) ps.close();
if (con != null) pool.returnConnection(con);
}
}
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!-- searchMember.jsp -->
<%
String mode = request.getParameter("mode");
if (mode == null || mode.trim().equals("")){%>
<script type="text/javascript">
alert("정상적인 경로로 들어오지 않았습니다.")
location.href="<%=request.getContextPath()%>/login.login.jsp"
</script>
<% return;
}
%>
<html>
<head>
<title>회원정보찾기</title>
<link rel="stylesheet" type="text/css" href="../style.css">
<script type="text/javascript">
function searchMember(mode){
if (f.name.value==""){
alert("이름을 입력해 주세요")
f.name.focus()
return false
}
if (f.ssn1.value==""){
alert("주민번호 앞자리를 입력해 주세요")
f.ssn1.focus()
return false
}
if (f.ssn2.value==""){
alert("주민번호 뒷자리를 입력해 주세요")
f.ssn2.focus()
return false
}
if (mode=='pw' && f.id.value==""){
alert("아이디를 입력해 주세요")
f.id.focus()
return false
}
return true
}
</script>
</head>
<body>
<div align="center">
<hr color="green" width="300">
<% if (mode.equals("id")){ %>
<h2>아 이 디 찾 기</h2>
<% }else { %>
<h2>비 밀 번 호 찾 기</h2>
<% } %>
<hr color="green" width="300">
<form name="f" action="searchMember_ok.jsp" method="post"
onsubmit="return searchMember('<%=mode%>')">
<table border="0" width="500" class="outline">
<tr>
<th class="m1">이름</th>
<td><input type="text" name="name" class="box"></td>
</tr>
<tr>
<th class="m1">주민번호</th>
<td><input type="text" name="ssn1" class="box" maxlength="6">-
<input type="password" name="ssn2" class="box" maxlength="7"></td>
</tr>
<% if (mode.equals("pw")){ %>
<tr>
<th class="m1">아이디</th>
<td><input type="text" name="id" class="box"></td>
</tr>
<% } %>
<tr>
<td align="center" colspan="2">
<input type="submit" value="찾기">
<input type="reset" value="다시작성">
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
만약 jsp 로 넘어올 때 가져온 mode 값이 id라면 아이디 찾기, password라면 비밀번호 찾기가 된다. 또 password찾기 할 때 아이디 값을 넣는 부분도 mode값이 password라면 생성되도록 만들어 준다.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!-- searchMember_ok.jsp -->
<jsp:useBean id="mbdao" class="my.member.MemberDAO"/>
<%
request.setCharacterEncoding("EUC-KR");
String name = request.getParameter("name");
String ssn1 = request.getParameter("ssn1");
String ssn2 = request.getParameter("ssn2");
String id = request.getParameter("id");
if (name == null || name.trim().equals("")){%>
<script type="text/javascript">
alert("정상적인 경로로 들어오지 않았습니다.")
location.href="<%=request.getContextPath()%>/login.login.jsp"
</script>
<% return;
}
String msg;
if (id == null) {
msg = "아이디 : " + mbdao.searchMember(name, ssn1, ssn2, id);
}else {
msg = "패스워드 : " + mbdao.searchMember(name, ssn1, ssn2, id);
}
%>
<script type="text/javascript">
alert("<%=msg%>")
self.close()
</script>
이렇게 내 홈페이지에 회원제를 구축해 보았다.
jsp... 프론트엔드 언어는 잘 모르지만 항상 전반 상황을 이해해야 가장 효율적인 코드가 나온다는 걸 잊지 말자.