<jsp:useBean>
액션 태그src/main/java
오른쪽 클릭하여 새 패키지 kr.web.member
생성하고 새 클래스 MemberVO
생성package kr.web.member;
// 자바빈
public class MemberVO {
// 프로퍼티
private String id;
private String password;
private String name;
private String email;
private String address;
// Getters and Setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
ch16-javaBeans
생성하고 새 JSP 파일 membershipForm.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입 입력 폼</title>
</head>
<body>
<form action="processJoining.jsp" method="post">
아이디 : <input type="text" name="id" size="10"><br>
비밀번호 : <input type="password" name="password" size="10"><br>
이름 : <input type="text" name="name" size="10"><br>
이메일 : <input type="email" name="email" size="10"><br>
주소 : <input type="text" name="address" size="10"><br>
<input type="submit" value="회원 가입">
</form>
</body>
</html>
processJoining.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.web.member.MemberVO" %>
<%
// 전송된 데이터 인코딩 처리
request.setCharacterEncoding("UTF-8");
// 자바빈 생성
MemberVO member = new MemberVO();
// 전송된 데이터를 request로부터 추출해서 setter 메서드를 이용해 자바빈의 프로퍼티에 저장
member.setId(request.getParameter("id"));
member.setPassword(request.getParameter("password"));
member.setName(request.getParameter("name"));
member.setEmail(request.getParameter("email"));
member.setAddress(request.getParameter("address"));
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입</title>
</head>
<body>
<h3>회원 정보 보기</h3>
아이디 : <%= member.getId() %><br>
비밀번호 : <%= member.getPassword() %><br>
이름 : <%= member.getName() %><br>
이메일 : <%= member.getEmail() %><br>
주소 : <%= member.getAddress() %>
</body>
</html>
<jsp:useBean>
<jsp:setProperty>
<jsp:getProperty>
ch16-javaBeans
폴더의 하위 폴더로 byAction
생성하고 ch16-javaBeans
폴더의 membershipForm.jsp
를 복사하여 byAction
폴더에 붙여넣기byAction
폴더에 새 JSP 파일 processJoining.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
// 전송된 데이터 인코딩 처리
request.setCharacterEncoding("UTF-8");
%>
<%-- 자바빈 객체 생성 --%>
<jsp:useBean id="member" class="kr.web.member.MemberVO"/> <%-- <jsp:useBean>은 시작 태그와 끝 태그가 있지만, 내용이 없는 태그이므로 일반적으로 단독 태그로 사용; id 속성에 자바빈의 식별자, class 속성에 패키지명까지 포함한 전체 클래스명을 명시 --%>
<%-- <jsp:setProperty>는 request에 저장된 데이터의 파라미터명과 자바빈의 프로퍼티명을 대조해서 일치하면 전송된 데이터를 자바빈의 프로퍼티에 저장 --%>
<jsp:setProperty name="member" property="*"/> <%-- name 속성에 자바빈의 식별자, property 속성에 자바빈의 프로퍼티를 명시 --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입</title>
</head>
<body>
아이디 : <jsp:getProperty property="id" name="member"/><br> <%-- <jsp:getProperty>는 getter 메서드에 비해 이점이 없으므로 잘 사용되지 않음 --%>
비밀번호 : <jsp:getProperty property="password" name="member"/><br>
이름 : <jsp:getProperty property="name" name="member"/><br>
이메일 : <jsp:getProperty property="email" name="member"/><br>
주소 : <jsp:getProperty property="address" name="member"/>
</body>
</html>
context.xml
을 통해 커넥션 풀 사용 가능m1_member
m1_member
입력 후 Next-Next-Generate web.xml depolyment descriptor 선택 후 FinishC:\javaWork\apps
에서 ojdbc8.jar
를 복사하여 C:\javaWork\workspace_jsp\m1_member\src\main\webapp\WEB-INF\lib
에 붙여넣기src/main/webapp
폴더 오른쪽 클릭하고 새 폴더 sql
생성 후 table.sql
생성CREATE TABLE smember(
num NUMBER PRIMARY KEY,
id VARCHAR2(12) UNIQUE NOT NULL,
name VARCHAR2(30) NOT NULL,
passwd VARCHAR2(12) NOT NULL,
email VARCHAR2(50) NOT NULL,
phone VARCHAR2(15),
reg_date DATE NOT NULL
);
CREATE SEQUENCE smember_seq;
src/main/webapp/META-INF
에 context.xml
생성<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!--
name : 식별자
auth : 컨테이너를 자원 관리자로 지정
type : 생성되는 객체의 자료형
maxTotal : 커넥션 풀에서 생성되는 최대 커넥션 수
maxIdle : 커넥션 풀 유지를 위한 최대 대기 커넥션 수
-->
<Resource name="jdbc/xe"
auth="Container"
type="javax.sql.DataSource"
username="scott"
password="tiger"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@localhost:1521:xe"
maxTotal="20"
maxIdle="10" />
</Context>
webapp
폴더 오른쪽 클릭 후 새 폴더 css
생성하고 새 CSS 파일 layout.css
생성@charset "UTF-8";
.page-main {
width: 900px;
margin: 0 auto;
}
.result-display {
width: 400px;
height: 200px;
border: 1px solid #000;
/* <div>를 화면 중앙에 배치하기 위한 설정 */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* <div>의 내용을 <div>의 중앙에 배치하기 위한 설정 */
display: flex;
align-items: center; /* 세로 정렬 */
justify-content: center; /* 가로 정렬 */
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
/* 회원 가입, 수정 폼 */
form {
width: 500px;
margin: 0 auto;
padding: 10px 10px 10px 30px;
border: 1px solid #000;
}
ul {
list-style: none;
}
label {
width: 120px;
float: left;
}
webapp
폴더 오른쪽 클릭 후 새 폴더 js
생성하고 jquery-3.6.0.min.js
파일을 해당 폴더로 이동src/main/java
오른쪽 클릭하여 새 패키지 kr.member.vo
생성하고 새 클래스 MemberVO
생성package kr.member.vo;
import java.sql.Date;
public class MemberVO {
private int num; // 회원 번호
private String id; // 아이디
private String name; // 이름
private String passwd; // 비밀번호
private String email; // 이메일
private String phone; // 전화번호
private Date reg_date; // 가입일
// 비밀번호 체크
public boolean isCheckedPassword(String userPasswd) {
if(passwd.equals(userPasswd)) { // 비밀번호 일치
return true;
}
return false; // 비밀번호 불일치
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Date getReg_date() {
return reg_date;
}
public void setReg_date(Date reg_date) {
this.reg_date = reg_date;
}
}
webapp
폴더 오른쪽 클릭 후 새 폴더 views
생성하고 새 JSP 파일 main.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 관리 메인</title>
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/layout.css">
</head>
<%
String user_id = (String)session.getAttribute("user_id");
%>
<body>
<div class="page-main">
<h1>회원 관리 메인</h1>
<div class="align-right">
<%
if(user_id==null) { // 로그인되어 있지 않은 경우
%>
<a href="registerUserForm.jsp">회원 가입</a>
<a href="loginForm.jsp">로그인</a>
<%
}
else { // 로그인된 경우
%>
<a href="myPage.jsp">MyPage</a>
[<b><%= user_id %></b>님 로그인 중]
<a href="logout.jsp">로그아웃</a>
<%
}
%>
</div>
</div>
</body>
</html>
registerUserForm.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입</title>
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/layout.css">
<script type="text/javascript" src="<%= request.getContextPath() %>/js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
var count = 0;
$('#confirm_id').click(function() {
if($('#id').val().trim()=='') {
alert('아이디를 입력하세요!');
$('#id').val('').focus();
return;
}
// 서버 연동
$.ajax({
url:'confirmId.jsp',
type:'post',
data:{id:$('#id').val()},
dataType:'json',
cache:false,
timeout:30000,
success:function(param) {
if(param.result=='idDuplicated') {
count = 0;
$('#id_signed').text('아이디 중복').css('color', 'red');
$('#id').val('').focus();
}
else if(param.result=='idNotFound') {
count = 1;
$('#id_signed').text('사용 가능한 아이디').css('color', 'black');
}
else { // 정상적인 값이 아닌 경우
count = 0;
alert('오류 발생!');
}
},
error:function() {
count = 0;
alert('네트워크 에러 발생!');
}
}); // end of ajax
}); // end of click
$('#register_form #id').keyup(function() {
count = 0;
$('#id_signed').text('');
}); // end of keyup
$('#register_form').submit(function() {
if($('#id').val().trim()=='') {
alert('아이디를 입력하세요!');
$('#id').val('').focus();
return false;
}
if(count==0) {
alert('아이디 중복 체크 필수!');
return false;
}
if($('#name').val().trim()=='') {
alert('이름을 입력하세요!');
$('#name').val('').focus();
return false;
}
if($('#passwd').val().trim()=='') {
alert('비밀번호를 입력하세요!');
$('#passwd').val('').focus();
return false;
}
if($('#email').val().trim()=='') {
alert('이메일을 입력하세요!');
$('#email').val('').focus();
return false;
}
}); // end of submit
});
</script>
</head>
<body>
<div class="page-main">
<h1>회원 가입</h1>
<form action="registerUser.jsp" method="post" id="register_form">
<ul>
<li>
<label for="id">아이디</label>
<input type="text" name="id" id="id" size="7" maxlength="12">
<input type="button" id="confirm_id" value="중복 확인">
<span id="id_signed"></span>
</li>
<li>
<label for="name">이름</label>
<input type="text" name="name" id="name" maxlength="10">
</li>
<li>
<label for="passwd">비밀번호</label>
<input type="password" name="passwd" id="passwd" maxlength="12">
</li>
<li>
<label for="email">이메일</label>
<input type="email" name="email" id="email" maxlength="50">
</li>
<li>
<label for="phone">전화번호</label>
<input type="text" name="phone" id="phone" maxlength="15">
</li>
</ul>
<div class="align-center">
<input type="submit" value="등록">
<input type="button" value="홈으로" onclick="location.href = 'main.jsp';">
</div>
</form>
</div>
</body>
</html>
confirmId.jsp
생성<%@ page language="java" contentType="text/plain; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ page import="kr.member.dao.MemberDAO" %>
<%@ page import="kr.member.vo.MemberVO" %>
<%
// 전송된 데이터 인코딩 처리
request.setCharacterEncoding("UTF-8");
// 전송된 데이터 반환
String id = request.getParameter("id");
MemberDAO dao = MemberDAO.getInstance();
MemberVO member = dao.checkMember(id);
if(member!=null) { // 아이디가 중복된 경우
%>
{"result":"idDuplicated"}
<%
}
else { // 아이디가 중복되지 않은 경우
%>
{"result":"idNotFound"}
<%
}
%>
registerUser.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.member.dao.MemberDAO" %>
<%
// 전송된 데이터 인코딩 처리
request.setCharacterEncoding("UTF-8");
%>
<jsp:useBean id="member" class="kr.member.vo.MemberVO"/>
<jsp:setProperty property="*" name="member"/>
<%
MemberDAO dao = MemberDAO.getInstance();
dao.insertMember(member);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입</title>
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/layout.css">
</head>
<body>
<div class="page-main">
<h1>회원 가입 완료</h1>
<div class="result-display">
<div class="align-center">
회원 가입 성공!<br>
<button type="button" onclick="location.href = 'main.jsp';">홈으로</button>
</div>
</div>
</div>
</body>
</html>
loginForm.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 폼</title>
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/layout.css">
<script type="text/javascript">
window.onload = function() {
document.getElementById('login_form').onsubmit = function() {
var id = document.getElementById('id');
if(id.value.trim()=='') {
alert('아이디를 입력하세요!');
id.value = '';
id.focus();
return false;
}
var passwd = document.getElementById('passwd');
if(passwd.value.trim()=='') {
alert('비밀번호를 입력하세요!');
passwd.value = '';
passwd.focus();
return false;
}
};
};
</script>
</head>
<body>
<div class="page-main">
<h1>로그인</h1>
<form action="login.jsp" method="post" id="login_form">
<ul>
<li>
<label for="id">아이디</label>
<input type="text" name="id" id="id" maxlength="12">
</li>
<li>
<label for="passwd">비밀번호</label>
<input type="password" name="passwd" id="passwd" maxlength="12">
</li>
</ul>
<div class="align-center">
<input type="submit" value="로그인">
<input type="button" value="홈으로" onclick="location.href = 'main.jsp';">
</div>
</form>
</div>
</body>
</html>
login.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.member.dao.MemberDAO" %>
<%@ page import="kr.member.vo.MemberVO" %>
<%
// 전송된 데이터 인코딩 처리
request.setCharacterEncoding("UTF-8");
// 전송된 데이터 반환
String id = request.getParameter("id");
String passwd = request.getParameter("passwd");
MemberDAO dao = MemberDAO.getInstance();
// 아이디 존재 여부 확인
MemberVO member = dao.checkMember(id);
boolean check = false;
if(member!=null) { // 아이디 존재
// 사용자가 입력한 비밀번호와 데이터베이스에 저장된 비밀번호 일치 여부 확인
check = member.isCheckedPassword(passwd);
}
if(check) { // 인증 성공
// 로그인 처리
session.setAttribute("user_num", member.getNum());
session.setAttribute("user_id", id);
response.sendRedirect("main.jsp");
}
else { // 인증 실패
%>
<script type="text/javascript">
alert('아이디 또는 비밀번호가 불일치!');
history.go(-1);
</script>
<%
}
%>
logout.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
// 로그아웃
session.invalidate();
response.sendRedirect("main.jsp");
%>
src/main/java
오른쪽 클릭하여 새 패키지 kr.member.dao
생성하고 새 클래스 MemberDAO
생성package kr.member.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import kr.member.vo.MemberVO;
public class MemberDAO {
// 싱글턴 패턴
private static MemberDAO instance = new MemberDAO();
public static MemberDAO getInstance() {
return instance;
}
private MemberDAO() {}
// context.xml에서 설정 정보를 읽어들여 커넥션 풀로부터 커넥션을 할당받음
private Connection getConnection() throws Exception {
Context initCtx = new InitialContext();
DataSource ds = (DataSource)initCtx.lookup("java:comp/env/jdbc/xe");
return ds.getConnection();
}
// 자원 정리
private void executeClose(ResultSet rs, PreparedStatement pstmt, Connection conn) {
if(rs!=null) try {rs.close();} catch(SQLException e) {}
if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
if(conn!=null) try {conn.close();} catch(SQLException e) {}
}
// 회원 가입
public void insertMember(MemberVO member) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션을 할당
conn = getConnection();
// SQL문 작성
sql = "INSERT INTO smember (num, id, name, passwd, email, phone, reg_date) "
+ "VALUES (smember_seq.NEXTVAL, ?, ?, ?, ?, ?, SYSDATE)";
// PrepearedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setString(1, member.getId());
pstmt.setString(2, member.getName());
pstmt.setString(3, member.getPasswd());
pstmt.setString(4, member.getEmail());
pstmt.setString(5, member.getPhone());
// SQL문 실행
pstmt.executeUpdate();
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
executeClose(null, pstmt, conn);
}
}
// 회원 상세 정보
public MemberVO getMember(int num) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
MemberVO member = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션을 할당
conn = getConnection();
// SQL문 작성
sql = "SELECT * FROM smember WHERE num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, num);
// SQL문을 실행해서 결과 행을 ResultSet에 담아 반환
rs = pstmt.executeQuery();
if(rs.next()) {
member = new MemberVO(); // 자바빈 객체 생성
member.setNum(rs.getInt("num"));
member.setId(rs.getString("id"));
member.setPasswd(rs.getString("passwd"));
member.setName(rs.getString("name"));
member.setEmail(rs.getString("email"));
member.setPhone(rs.getString("phone"));
member.setReg_date(rs.getDate("reg_date"));
}
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
executeClose(rs, pstmt, conn);
}
return member;
}
// 아이디 중복 체크, 로그인 체크
public MemberVO checkMember(String id) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
MemberVO member = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = getConnection();
// SQL문 작성
sql = "SELECT * FROM smember WHERE id=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setString(1, id);
// SQL문을 실행하고 결과 행을 ResultSet에 담아 반환
rs = pstmt.executeQuery();
if(rs.next()) {
member = new MemberVO(); // 자바빈 객체 생성
member.setId(rs.getString("id"));
member.setNum(rs.getInt("num"));
member.setPasswd(rs.getString("passwd"));
}
}
catch(Exception e) {
// e.printStackTrace(); // UI는 상황에 따라 정상 화면에 값만 null로 출력되고, 콘솔에는 에러 메시지가 출력됨
throw new Exception(e); // UI는 에러 페이지가 전송되고, 콘솔에는 에러 메시지가 출력됨
}
finally {
// 자원 정리
executeClose(rs, pstmt, conn);
}
return member;
}
// 회원 정보 수정
public void updateMember(MemberVO member) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql= null;
try {
// 커넥션 풀로부터 커넥션을 할당
conn = getConnection();
// SQL문 작성
sql = "UPDATE smember SET name=?, passwd=?, email=?, phone=? WHERE num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setString(1, member.getName());
pstmt.setString(2, member.getPasswd());
pstmt.setString(3, member.getEmail());
pstmt.setString(4, member.getPhone());
pstmt.setInt(5, member.getNum());
// SQL문 실행
pstmt.executeUpdate();
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
executeClose(null, pstmt, conn);
}
}
// 회원 탈퇴(회원 정보 삭제)
public void deleteMember(int num) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql= null;
try {
// 커넥션 풀로부터 커넥션을 할당
conn = getConnection();
// SQL문 작성
sql = "DELETE FROM smember WHERE num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, num);
// SQL문 실행
pstmt.executeUpdate();
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
executeClose(null, pstmt, conn);
}
}
}