이 포스팅은 '로그인 유지 프로그램' 포스팅과 이어지는 포스팅입니다.
기능은 '회원 정보 수정' 과 '회원 가입' 기능이 추가됩니다 !
https://creamilk88.tistory.com/103 을 참고하여 이어지는 포스팅으로 참고해주세요!
[ 잠깐 Review ! ]
* Cookie와 HttpSession
→ HTTP : Stateless (상태 정보 유지 X)
⇒ 상태 정보 유지 방법 !
① Cookie - 클라이언트 측에 저장 : 용량, 타입 제한 O
② Session - 서버 측에 저장 : 용량, 타입 제한 X
* JSP 내장 객체
request | session | Application (ServletContext) | |
유효범위 | response 될 때 까지 | 일정 조건 (session - timeout) | 웹 어플리케이션 종료까지 |
setAttribute(name, value) getAtrribute(name) |
[ 프로그램 진행 원리 및 개요 ]
Model2 설계방식 ( + MVC / Singleton / Front Controller Pattern 적용)
4번 기능 : 회원 정보 수정
5+6번 기능 : 회원 가입 (+아이디 중복 체크) 기능
[ 전체 구현 코드 ]
DB Table
Model
/MemberVO.java
https://creamilk88.tistory.com/103 에서 제공하는 코드와 동일합니다.
/ProductDAO.java
findMemberById(), login() method는 앞 포스팅에서 활용한 1,2 번 기능을 구현하기 위한 method입니다.
나머지 method는 이번 포스팅에서 새로운 기능을 구현하기 위해 추가된 method입니다.
package org.kosta.model;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MemberDAO {
//singleton 적용
private static MemberDAO instance = new MemberDAO();
//JDBC에 필요한 변수
private String driver = "oracle.jdbc.OracleDriver";
private String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe";
private String username = "scott";
private String userpass = "tiger";
//class 생성 단계에서 singleton으로 한번 생성 + driver loading
//사실 driver loading은 현재 java version에서는 따로 기재해주지 않아도,
//자동으로 loading된다 !
private MemberDAO() {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//getInstance() method : 생성자 객체 반환용
public static MemberDAO getInstance() {
return instance;
}
//closeAll method 1
public void closeAll(PreparedStatement pstmt, Connection con)
throws SQLException {
if (pstmt != null)
pstmt.close();
if (con != null)
con.close();
}
//closeAll method 2
public void closeAll(ResultSet rs, PreparedStatement pstmt, Connection con)
throws SQLException {
if (rs != null)
rs.close();
//재사용
this.closeAll(pstmt, con);
}
/*
* 1번 기능 : 아이디로 회원정보 조회
* findMemberById(String):MemberVO
*/
public MemberVO findMemberById(String id) throws SQLException {
MemberVO vo = null;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DriverManager.getConnection(url, username, userpass);
String sql = "SELECT name, address FROM web_member "
+ "WHERE id = ?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, id);
rs = pstmt.executeQuery();
if(rs.next()) {
vo = new MemberVO(id, null, rs.getString(1),rs.getString(2));
}
} finally {
closeAll(rs, pstmt, con);
}
return vo;
}
/*
* 2번 기능 : 로그인 기능
* login(MemberVO):MemberVO
*/
public MemberVO login(MemberVO vo) throws SQLException {
MemberVO mvo = null;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DriverManager.getConnection(url, username, userpass);
String sql = "SELECT name, password, address FROM web_member "
+ "WHERE id=? AND password=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, vo.getId());
pstmt.setString(2, vo.getPassword());
rs = pstmt.executeQuery();
if(rs.next()){
mvo = new MemberVO(vo.getId(), rs.getString("password"),
rs.getString("name"),rs.getString("address"));
}
} finally {
closeAll(rs, pstmt, con);
}
return mvo;
}
/*
* 4번 기능 : 회원 정보 수정 기능
* updateMember(MemberVO):void
*/
public void updateMember(MemberVO vo) throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DriverManager.getConnection(url, username, userpass);
StringBuilder sql = new StringBuilder();
sql.append("UPDATE web_member ");
sql.append("SET password=?, name=?, address=? ");
sql.append("WHERE id=?");
pstmt = con.prepareStatement(sql.toString());
//password
pstmt.setString(1, vo.getPassword());
//name
pstmt.setString(2, vo.getName());
//address
pstmt.setString(3, vo.getAddress());
//id
pstmt.setString(4, vo.getId());
pstmt.executeUpdate();
} finally {
closeAll(pstmt, con);
}
}
/*
* 5번 기능 : 회원 가입 기능
* register(MemberVO):void
*/
public void register(MemberVO vo) throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DriverManager.getConnection(url, username, userpass);
StringBuilder sql = new StringBuilder();
sql.append("INSERT INTO web_member(id, password, name, address) ");
sql.append("VALUES (?, ?, ?, ?)");
pstmt = con.prepareStatement(sql.toString());
pstmt.setString(1, vo.getId());
pstmt.setString(2, vo.getPassword());
pstmt.setString(3, vo.getName());
pstmt.setString(4, vo.getAddress());
pstmt.executeUpdate();
} finally {
closeAll(pstmt, con);
}
}
/*
* 6번 기능 : 아이디 중복 체크 기능
* idCheck(String id):boolean
*/
public boolean idCheck(String id) throws SQLException {
boolean flag = false;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DriverManager.getConnection(url, username, userpass);
String sql = "SELECT COUNT(*) FROM web_member WHERE id=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, id);
rs = pstmt.executeQuery();
if(rs.next() && rs.getInt(1) > 0) //중복 id가 있으면
flag = true; //flag를 true로 변환
} finally {
closeAll(rs, pstmt, con);
}
return flag;
}
}//class
View
/index.jsp
<%@page import="org.kosta.model.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<div class="container">
<h4>
<a href="index.jsp"><img class="home-image" src="home.png">Home</a>
</h4>
<hr>
<h3>Model2 회원 관리</h3>
<a href="findmemberbyid.jsp">회원 검색</a><br>
<%
//로그인 여부 확인 방법
//(session 유무 확인 + 로그인 시 할당한 attribute 존재 확인)
HttpSession session = request.getSession(false);
// (A && B) : A가 false이면 뒤에 B는 확인하지 않는다.
if (session != null && session.getAttribute("mvo") != null) {
MemberVO mvo = (MemberVO) session.getAttribute("mvo");
%>
<br><%=mvo.getAddress()%>에 사는
<%=mvo.getName()%>님 로그인 상태<br>
<a href="front?command=logout">로그아웃</a><br>
<%-- 회원정보 수정 기능 --%>
<a href="update-form.jsp">회원정보 수정</a>
<%
} else {
%>
<a href="login.jsp">로그인 페이지로</a><br><br>
<%-- 회원 가입 기능 --%>
<a href="register-form.jsp">회원 가입하기</a>
<%
}
%>
</div>
</body>
</html>
/error.jsp
https://creamilk88.tistory.com/103 에서 제공하는 코드와 동일합니다.
-- 4번 기능 : 회원 정보 수정 기능
: 로그인에서 이용한 session을 그대로 유지하여 이용한다. (새로운 세션을 생성하지 않는다!)
/update-form.jsp
<%@page import="org.kosta.model.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>회원 정보 수정 form</title>
</head>
<body>
<div class="container">
<a href="index.jsp"><img class="home-image" src="home.png">Home</a>
<hr>
<%--
로그인 유무에 따라 다른 결과 값을 보여준다
로그인 여부 확인 후 회원 정보 수정 권한을 준다
--%>
<%
//로그인한 사용자인지 확인
//(1.세션 유무와 2.세션 내의 인증정보 유무)
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("mvo") != null){
MemberVO mvo = (MemberVO) session.getAttribute("mvo");
%>
<h4>회원 정보 수정</h4>
<form action="front" method="POST">
<input type="hidden" name="command" value="updateMember">
<%-- readonly="readonly" : 수정을 불가능하게 하는 속성 --%>
아이디 <input type="text" name="id" readonly="readonly"
value="<%=mvo.getId()%>"><br>
패스워드 <input type="password" name="password"
value="<%=mvo.getPassword()%>"><br>
이름 <input type="text" name="name"
value="<%=mvo.getName()%>"><br>
주소 <input type="text" name="address"
value="<%=mvo.getAddress()%>"><br>
<input type="submit" value="수정하기">
</form>
<% } else { %>
로그인 후 이용 가능한 서비스입니다.<br>
로그인 해주세요!<br><br>
<a href="login.jsp">로그인 페이지로</a>
<% } %>
</div>
</body>
</html>
/update-result.jsp
<%@page import="org.kosta.model.MemberVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>css test</title>
</head>
<body>
<div class="container">
<a href="index.jsp"><img class="home-image" src="home.png">Home</a>
<hr>
<h4> 회원정보가 성공적으로 수정 완료되었습니다.</h4><br>
<%
/*새로 세션을 만들지 않고, login부터 이어져온 session을 사용한다.
* -> UpdateMemberController에 의해 attribute정보가 새로 바뀐 정보를
* 가져와서 활용한다. (session.getAttribute("mvo", mvo))
*/
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("mvo")!=null) {
MemberVO mvo = (MemberVO) session.getAttribute("mvo"); %>
아이디 : <%=mvo.getId() %><br>
패스워드 : <%=mvo.getPassword() %><br>
이름 : <%=mvo.getName() %><br>
주소 : <%=mvo.getAddress() %><br>
<% } else { %>
<script type="text/javascript">
alert("로그인을 먼저 해주세요!");
location.href = "login.jsp";
</script>
<% } %>
</div>
</body>
</html>
-- 5번 기능 : 회원 가입 기능 (+ 아이디 중복체크 기능도 register-form.jsp에 포함됨)
/register-form.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>회원가입 form</title>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<script type="text/javascript">
function CheckPassword() {
//getting object
var passwordObj = document.registerForm.password;
var password_checkObj = document.registerForm.password_check;
var flagObj = document.registerForm.flag;
var idObj = document.registerForm.id;
//getting values
if (passwordObj.value !== password_checkObj.value){
alert("비밀번호를 확인하세요!");
//setting values
passwordObj.value = "";
password_checkObj.value = "";
//return값 설정
return false;
}
//flagObj.value : 인증받은 아이디 (idcheck-ok.jsp 팝업에서 할당한 아이디)
//idObj.value : 사용자가 입력한 아이디
if(flagObj.value !== idObj.value){
alert("인증받은 아이디가 아닙니다.\n아이디 중복확인을 하세요!")
return false;
}
}
function CheckId(){
var id = document.registerForm.id.value;
if (id === ""){
alert("아이디를 입력하세요");
} else {
var path = "front?command=idcheck&id=" + id;
window.open(path, "idpopup",
"width=450, height=250, top=150, left=200");
}
}
</script>
</head>
<body>
<div class="container">
<a href="index.jsp"><img class="home-image" src="home.png">Home</a>
<hr>
<%-- CheckPassword()
: password와 password_check 같은 지 여부 확인 후 return--%>
<form action="front" method="POST"
name="registerForm" onsubmit="return CheckPassword()">
<input type="hidden" name="command" value="register">
<%-- 아이디 중복 확인을 위한 hidden --%>
<input type="hidden" name="flag" value="">
아이디 <input type="text" name="id" required="required">
<input type="button" value="중복확인" onclick="CheckId()"><br>
패스워드 <input type="password" name="password" required="required"><br>
패스워드 확인 <input type="password" name="password_check" required="required"><br>
이름 <input type="text" name="name" required="required"><br>
주소 <input type="text" name="address" required="required"><br>
<input type="submit" value="가입하기">
</form>
</div>
</body>
</html>
/register-result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>회원가입 완료</title>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
</head>
<body>
<div class="container">
<a href="index.jsp"><img class="home-image" src="home.png">Home</a>
<hr>
회원가입이 완료되었습니다.<br>
축하드립니다!<br>
</div>
</body>
</html>
-- 6번 기능 : 아이디 중복 체크 기능 (팝업)
/idcheck-ok.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>사용 가능 아이디</title>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<script type="text/javascript">
function closePopup() {
//이 팝업창을 실행 시킨 창은 opener 객체이다.
//opener 객체를 가져온다
var of = window.opener.registerForm;
//flag값을 id로 바꿔주기
of.flag.value = "<%=request.getParameter("id")%>";
//password로 마우스 커서 옮기기
of.password.focus();
//자신(팝업창)을 종료한다
self.close();
}
</script>
</head>
<body bgcolor="yellow" onunload="closePopup()">
<%=request.getParameter("id")%>는 사용 가능한 아이디입니다.
<br>
<br>
<br>
<input type="button" value="확인" onclick="closePopup()">
</body>
</html>
/idcheck-fail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<head>
<meta charset="UTF-8">
<title>사용 불가 아이디</title>
<link rel="stylesheet" type="text/css" href="css/mystyle.css">
<script type="text/javascript">
function closePopup(){
//이 팝업창을 실행 시킨 창은 opener 객체이다.
//opener 안에 있는 id 객체를 가져온다
var idObj = opener.document.registerForm.id;
//hidden의 flag도 가져온다
var flagObj = opener.document.registerForm.flag;
//id + flag 초기화 시키고 & id로 마우스 커서 옮기기
idObj.value="";
flagObj.value= "";
idObj.focus();
//자신(팝업창)을 종료한다
self.close();
}
</script>
</head>
<body bgcolor="orange" onunload="closePopup()">
<%=request.getParameter("id") %>는 사용 불가능한 아이디입니다.
<br><br><br>
<input type="button" value="확인" onclick="closePopup()">
</body>
</html>
Controller
/DispatcherServlet.java
/controller.java
https://creamilk88.tistory.com/103 에서 제공하는 코드와 동일합니다.
/ HandlerMapping.java
package org.kosta.controller;
/*
* 개별 컨트롤러 객체 생성을 전담하는 팩토리 클래스
*/
public class HandlerMapping {
// singleton pattern으로 객체 생성
private static HandlerMapping instance = new HandlerMapping();
private HandlerMapping() { }
public static HandlerMapping getInstance() {
return instance;
}
/* create method() 생성
* command에 따라 개별의 Controller를 만들어주는 기능
*/
public Controller create(String command) {
Controller controller = null;
if(command.contentEquals("findmemberbyid"))
controller = new FindMemberByIdController();
else if(command.contentEquals("login"))
controller = new LoginController();
else if(command.contentEquals("logout"))
controller = new LogoutController();
else if(command.contentEquals("updateMember"))
controller = new UpdateMemberController();
else if(command.contentEquals("register"))
controller = new RegisterController();
else if(command.contentEquals("idcheck"))
controller = new IdCheckController();
return controller;
}
}
-- 4번 기능 : 회원 정보 수정 (UDPATE/SET) 기능 controller
: 로그인에서 이용한 session을 그대로 유지하여 이용한다.
/UpdateMemberController.java
package org.kosta.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.kosta.model.MemberDAO;
import org.kosta.model.MemberVO;
public class UpdateMemberController implements Controller {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
String url = null;
// request.getSession(false)를 통해 새로운 세션 생성을 방지한다!
HttpSession session = request.getSession(false);
// <로그인 여부 확인>
// 1. session이 있고 + 2. session 정보가 있으면,
if (session != null && session.getAttribute("mvo") != null) {
// 1) update-form.jsp로부터 정보를 받아온다.
String id = request.getParameter("id");
String password = request.getParameter("password");
String name = request.getParameter("name");
String address = request.getParameter("address");
MemberVO updateMemberVO = new MemberVO(id, password, name, address);
// 2) DAO(Moel)과 연동해서, update를 실행해준다.
MemberDAO.getInstance().updateMember(updateMemberVO);
// 3) session에 새로 수정된 정보를 담아준다.
session.setAttribute("mvo", updateMemberVO);
// 4) url을 View(update-result.jsp)에 redirect방식으로 보낸다.
url = "redirect:update-result.jsp";
// session이 없으면 home(시작페이지)로 넘긴다.
} else {
url = "redirect:index.jsp";
}
return url;
}
}
-- 5번 기능 : 회원 가입 기능 (INSERT) controller
/RegisterController.java
package org.kosta.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.kosta.model.MemberDAO;
import org.kosta.model.MemberVO;
public class RegisterController implements Controller {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response)
throws Exception {
//register-form.jsp에서 form에 입력된 값 받아오기
String id = request.getParameter("id");
String password = request.getParameter("password");
String name = request.getParameter("name");
String address = request.getParameter("address");
MemberVO registerMemberVO = new MemberVO(id, password, name, address);
// VO 존재 유무 확인
if (registerMemberVO != null) { //VO가 있으면
//Model(DAO)과 연동
MemberDAO.getInstance().register(registerMemberVO);
// 연동 결과를 request에 담아 register-result와 공유
request.setAttribute("mvo", registerMemberVO);
}
//redirect 방식으로 view로 이동
return "redirect:register-result.jsp";
}
}
-- 6번 기능 : 회원 가입 시, 아이디 중복 확인 기능 controller
/IdCheckController.java
package org.kosta.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.kosta.model.MemberDAO;
public class IdCheckController implements Controller {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
// register-form.jsp에서 form에 입력된 id 받아오기
String id = request.getParameter("id");
// Model(DAO)와 연동
// DAO.idCheck는 중복 아이디가 있으면 true, 없으면 false
boolean flag = MemberDAO.getInstance().idCheck(id);
// id 중복 여부 확인
if (flag) // 중복 아이디가 없으면
return "idcheck-fail.jsp"; // fail로
else // 중복 아이디가 있으면
return "idcheck-ok.jsp"; // ok로
}
}
브라우저 결과 화면
'Java Web Programming > 4. JSP' 카테고리의 다른 글
[JSP] DB(SQL)의 date 타입을 이용한 Model 2 설계방식 프로그램 구현 (0) | 2020.09.04 |
---|---|
[JSP] Cookie 쿠키 & Session 세션 + Model 2 Architecture (MVC Pattern) 설계방식을 다시 한 번 정리하고 가자! (0) | 2020.09.04 |
[JSP/세션관리] 1단계_Cookie 쿠키 & Session 세션을 이용한 로그인 유지 프로그램 구현 (2) | 2020.09.01 |
[JSP/세션관리] JSP에서의 Session 세션 생성 원리(자동생성, 자동생성 방지 방법) (2) | 2020.09.01 |
[JSP/세션관리] Cookie 쿠키 & Session 세션 이란 무엇인가? (개념, 용도) (0) | 2020.08.31 |