member.js
/**
* 회원가입 유효성 검사
*/
var form = document.joinForm;
function join(){
//value를 조건식 안에서 사용하면
//값이 있을 때 true, 값이 없을 때 false
if(!form.id.value){
alert("아이디를 입력해주세요.");
form.id.focus();
return;
}
if(form.id.value.length < 4 || form.id.value.length > 16){
alert("아이디는 4자 이상, 16자 이하로 입력해주세요.")
form.id.focus();
return;
}
if(!form.name.value){
alert("이름을 입력해주세요.");
form.name.focus();
return;
}
if(!form.password.value){
alert("비밀번호를 입력해주세요.");
form.password.focus();
return;
}
//8자리 이상, 대문자, 소문자, 숫자, 특수문자 모두 포함되어 있는 지 검사
let reg = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/;
let hangleCheck = /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/
if(!reg.test(form.password.value)){
alert("비밀번호는 8자리 이상이어야 하며, 대문자/소문자/숫자/특수문자 모두 포함해야 합니다.");
form.password.focus();
return;
}
//같은 문자를 4번 사용할 수 없다.
if(/(\w)\1\1\1/.test(form.password.value)){
alert("같은 문자를 4번 이상 사용하실 수 없습니다.");
form.password.focus();
return;
}
//비밀번호 안에 아이디가 있을 때
if(form.password.value.search(form.id.value) != -1){
alert("비밀번호에 아이디를 포함할 수 없습니다.");
form.password.focus();
return;
}
//비밀번호에 한글이 있으면 안된다.
if(hangleCheck.test(form.password.value)){
alert("비밀번호에 한글을 사용할 수 없습니다.");
form.password.focus();
return;
}
//비밀번호에 공백을 포함할 수 없다.
if(form.password.value.search(/\s/) != -1){
alert("비밀번호에 공백 없이 입력해주세요.");
form.password.focus();
return;
}
if(form.password.value != form.password_re.value){
alert("비밀번호를 확인해주세요.");
form.password.focus();
return;
}
if(!form.id.readOnly){
alert("아이디 중복 검사를 진행해주세요.");
return;
}
form.submit();
}
$("input[name='id']").on("click", function(){
form.id.readOnly = false;
})
function checkId(){
var xhr = new XMLHttpRequest();
xhr.open("GET", "join_ok.jsp?id=" + document.getElementById("id").value, true);
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200){
document.getElementById("result").innerHTML = xhr.responseText.trim();
if(xhr.responseText.search("가능") != -1){
form.id.readOnly = true;
}
}
}
}
readOnly 가 true이면 아이디 검사가 잘되었다는 것. 중복검사가 잘되었다는 것.
false이면 중복 검사를 하지 않았거나, 중복 검사 후 수정하기 위해 변경했다거나.
아이디를 입력 후 중복검사를 하면 사용가능한 id라 나온다.
이 상태에서 아이디 창을 클릭하면 readOnly가 풀리고, 이 상태에서 회원가입 완료를 클릭하게 되면 '아이디 중복 검사를 진행해주세요' 라는 문구를 준다.
제대로 입력 후 회원가입 완료를 하면 login.jsp로 이동.
데이터베이스에 INSERT가 잘 되었다는 뜻이겠다.
사용자에게 입력 화면을 보여준 후 유효성 검사를 한다면 이렇게 js를 사용하면 되겠다.
자바스크립트 안에 있는 메서드(join())를 join.jsp에서 외부 자바스크립트로 추가해놓은 상태
<input type="button" onclick="join()" value="회원가입 완료">
<script src="member.js"></script>
member.js에 해당 html의 jsp에 포함이 되어있기 때문에 각각의 요소들의 DOM을 사용해 접근했다. 맨 처음 join전에는 많은 검사를 하다가 id 중복 검사를 checkId라는 걸 이용해 get방식으로 ajax를 사용했다.
현재 페이지 이동이 되지 않고 내가 원하는 부분에 DB 연산이 됨.
xhr.open("GET", "join_ok.jsp?id=" + document.getElementById("id").value, true);
따라서 이렇게 url을 보냈더니 여기에 대해서 join_ok에서는 전달받은 걸 useBean을 사용해 중복인지 아닌지를 검사했고, checkId가 true인지 fals인지에 따라서 알맞는 메시지가 바디 태그에 print 된다.
이 응답값을 다시 한번 member.js에서
document.getElementById("result").innerHTML = xhr.responseText.trim();
responseText 로 받아주고 trim으로 앞뒤 공백을 제거.
그 값을 result라는 id를 가진 태그에다 집어넣었고, 만약 그 메시지에 '가능'이라는 문구가 있다면 들어와서 더 이상 수정할 수 없게끔 true로 만들어주었다.
하지만 내가 마음에 들지 않을 때 다시 수정할 수 있게끔 하기 위해 다시 한번 클릭하면 readOnly를 풀어준다. 이 상태에서 readOnly가 true/false 이냐에 따라 중복검사 여부가 나뉜다. 하지 않았다면 '아이디 중복 검사를 진행해주세요' 문구가 나오고, 전부 완성되었다면 submit을 통해 해당 폼 태그가 action으로 이동하게 되는 것. 결과적으로 join_db에서 검사하고 login.jsp까지 오게되는 것.
join_db.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%request.setCharacterEncoding("UTF-8"); %>
<jsp:useBean class="dao.UserDAO" id="dao"/>
<jsp:useBean class="vo.UserVO" id="vo"/>
<jsp:setProperty property="*" name="vo"/>
<%
dao.join(vo);
response.sendRedirect("login.jsp");
%>
join.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="join_db.jsp" method="post" name="joinForm">
<p>
<label>아이디 : <input type="text" name="id" id="id"></label>
<input type="button" onclick="checkId()" value="중복 확인">
</p>
<p id="result"></p>
<p><label>이름 : <input type="text" name="name"></label></p>
<p><label>비밀번호 : <input type="password" name="password"></label></p>
<p><label>비밀번호 확인 : <input type="password" name="password_re"></label></p>
<p>
성별 :
남자 <input type="radio" name="gender" value="남자" checked>
여자 <input type="radio" name="gender" value="여자" checked>
</p>
<p>
<label>
우편번호 :
<input type="text" name="zipcode" class="postcodify_postcode5" value="" />
<button type="button" id="postcodify_search_button">검색</button><br />
</label>
</p>
<p>
<label>
주소 :
<input type="text" name="address" class="postcodify_address" value="" /><br />
</label>
</p>
<p>
<label>
상세 주소 :
<input type="text" name="address_detail" class="postcodify_details" value="" /><br />
</label>
</p>
<p>
<label>
참고 항목 :
<input type="text" name="address_etc" class="postcodify_extra_info" value="" /><br />
</label>
</p>
<input type="button" onclick="join()" value="회원가입 완료">
</form>
</body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//d1p7wdleee1q2z.cloudfront.net/post/search.min.js"></script>
<script> $(function() { $("#postcodify_search_button").postcodifyPopUp(); }); </script>
<script src="member.js"></script>
</html>
DBConnecter
이 커넥션 객체를 쓰는 건 UserDAO가 되겠다
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnecter {
//DAO에서 모든 메소드에 필요한 DB연결 문법을 미리 메소드에 선언해 놓는다.
public static Connection getconnection() {
Connection conn = null;
try {
//DB연결을 위한 정보를 입력한다(url, username, password).
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String user = "hr";
String pw = "hr";
//드라이버를 메모리에 할당한다.
Class.forName("oracle.jdbc.driver.OracleDriver");
//입력한 정보를 전달하여 드라이버를 통해 연결 객체를 가져온다.
conn = DriverManager.getConnection(url, user, pw);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
}
UserDAO
package dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import vo.UserVO;
//private int num;
//private String id;
//private String name;
//private String password;
//private String gender;
//private String zipcode;
//private String address;
//private String address_detail;
//private String address_etc;
public class UserDAO {
Connection conn; //외부 저장소인 DBMS를 드라이버를 통해 가져온 연결 객체
PreparedStatement pstm; //문자열안에 있는 SQL문을 객체로 저장, 변수가 들어갈 자리에 알맞는 값을 넣어줌, SQL문 실행시킴
ResultSet rs; //SELECT의 결과를 담는 객체
public void join(UserVO user) {
//SQL문 작성
String query = "INSERT INTO TBL_USER VALUES(SEQ_USER.NEXTVAL, ?, ?, ?, ?, ?, ?, ?, ?)";
try {
//connection객체를 전달받는다.
conn = DBConnecter.getconnection();
//위에서 작성한 쿼리문을 prepareStatement에 전달한다.
pstm = conn.prepareStatement(query);
//?자리에 알맞는 변수를 전달해준다.
pstm.setString(1, user.getId());
pstm.setString(2, user.getName());
pstm.setString(3, user.getPassword());
pstm.setString(4, user.getGender());
pstm.setString(5, user.getZipcode());
pstm.setString(6, user.getAddress());
pstm.setString(7, user.getAddress_detail());
pstm.setString(8, user.getAddress_etc());
//DML중 INSERT 쿼리를 실행하는 메소드를 사용한다.
pstm.executeUpdate();//결과 건수
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(pstm != null) {
pstm.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
//아이디 중복검사
public boolean checkId(String id) {
String query = "SELECT COUNT(ID) FROM TBL_USER WHERE ID = ?";
boolean check = false;
try {
//DBMS 연결 객체 가져오기
conn = DBConnecter.getconnection();
//String으로 선언된 쿼리를 pstm객체에 전달하기
pstm = conn.prepareStatement(query);
//SQL 쿼리에 ?가 있다면 알맞는 값으로 지정해주기
pstm.setString(1, id);
//쿼리 실행 후 결과를 rs객체에 담기
rs = pstm.executeQuery();
//행가져오기
rs.next();
//위에서 가져온 행의 열을 타입에 맞춰서 가져오기
check = rs.getInt(1) == 1; //0일 때 중복 없음(false), 1일 때 중복 있음(true)
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(rs != null) {
rs.close();
}
if(pstm != null) {
pstm.close();
}
if(conn != null) {
pstm.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
return check;
}
}