이메일 중복 검사
1. Servlet
package edu.kh.community.member.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import edu.kh.community.member.model.service.MemberService;
//----------------------------------------------------------
@WebServlet("/member/emailDupCheck")
public class EmailDupCheckServlet extends HttpServlet {
// 이메일 중복 검사(비동기 통신)
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 비동기 통신으로 전달된 파라미터(data 속성의 key값) 얻어오기
String memberEmail = req.getParameter("memberEmail");
// service 호출 -> dao -> db -> dao -> service -> servlet
// Exception을 던지면서 이동하기 때문에 Servlet엔 반드시 try~catch가 있어야 함.
try {
// 이메일 중복 검사 서비스 호출 후 결과 반환 받기
MemberService service = new MemberService();
int result = service.emailDupCheck(memberEmail);
// 보통 동기식 코드 작성 시, forward or redirect를 이용하여 새로운 페이지를 보이게 함
// 비동기 통신 시 응답은 응답은 화면이 아닌 '데이터'로 (데이터: String, int, JSON, XML...)
// 응답용 스트림을 이용하여 단순 데이터 전달만 하면 된다.
resp.getWriter().print(result);
// 응답용 스트림을 이용하여 result 출력
}catch(Exception e) {
e.printStackTrace();
}
}
}
2. Service
package edu.kh.community.member.model.service;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import static edu.kh.community.common.JDBCTemplate.*;
import edu.kh.community.member.model.dao.MemberDAO;
import edu.kh.community.member.model.vo.Member;
// -----------------------------------
public class MemberService {
private MemberDAO dao = new MemberDAO();
/** 이메일 중복 검사 Service
* @author memberEmail
* @return
*/
public int emailDupCheck(String memberEmail) throws Exception {
Connection conn = getConnection();
int result = dao.emailDupCheck(conn, memberEmail);
close(conn);
return result;
}
}
3. DAO
package edu.kh.community.member.model.dao;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import static edu.kh.community.common.JDBCTemplate.*;
import edu.kh.community.member.model.vo.Member;
// --------------------------------
public class MemberDAO {
private Statement stmt;
private PreparedStatement pstmt;
private ResultSet rs;
private Properties prop;
public MemberDAO() {
try {
prop = new Properties();
String filePath = MemberDAO.class.getResource("/edu/kh/community/sql/member-sql.xml").getPath();
prop.loadFromXML( new FileInputStream(filePath) );
} catch(Exception e) {
e.printStackTrace();
}
}
/** 이메일 중복검사 DAO
* @param conn
* @param memberEmail
* @return
*
*/
public int emailDupCheck(Connection conn, String memberEmail) throws Exception{
// 결과 저장용 변수 선언
int result = 0;
try {
// SQL 얻어오기
String sql = prop.getProperty("emailDupCheck");
//psmt 생성
pstmt = conn.prepareStatement(sql);
// 위치 홀더에 알맞은 값 세팅
pstmt.setString(1, memberEmail); // sql ?에 들어갈 값
/* 실행한 SQL
<entry key="emailDupCheck">
SELECT COUNT(*) FROM MEMBER
WHERE MEMBER_EMAIL = ?
AND SECESSION_FL = 'N'
</entry>
*/
// sql 실행 후 결과 반환 받기
rs = pstmt.executeQuery();
if(rs.next()) {
result = rs.getInt(1); // COUNT(*)
}
} finally {
close(rs);
close(pstmt);
}
return result;
}
이메일 인증번호 보내기
1. Servlet
package edu.kh.community.member.controller;
import java.io.IOException;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import javax.mail.internet.MimeMultipart;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import edu.kh.community.member.model.service.MemberService;
// -------------------------------------
@WebServlet("/member/sendEmail")
public class SendEmailServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 입력받은 이메일 얻어오기
String inputEmail = req.getParameter("inputEmail");
// -------------- 라이브러리 이용 -------------------
String subject = "[Commnity 프로젝트] 회원 가입 이메일 인증번호"; // 메일 제목
String fromEmail = "kdavin1221@gmail.com"; // 보내는 사람으로 표시될 이메일 (이메일 따라서 안될수도 있음)
String fromUsername = "관리자"; // 보내는 사람 이름
String toEmail = inputEmail; // 받는사람, 콤마(,)로 여러개 나열 가능
// 구글 이메일을 이용한 메일 보내기 (SMTP..기술 이름)
// 1. 구글 계정 생성(기존 이메일 사용해도됨)
// 2. 계정 -> 보안 설정 진행
// 1) 2단계 인증 추가
// 2) 앱 비밀번호 생성(메일, 서버컴퓨터 OS) -> 저장해두기 ( pbbnnudxezjycopr ) // 발급 받은 비밀번호.... 보안 주의!!!!!!!!!!!!
final String smtpEmail = "kdavin1221@gmail.com"; // 이메일
final String password = "pbbnnudxezjycopr"; // 발급 받은 비밀번호.... 보안 주의!!!!!!!!!!!!
// 메일 옵션 설정
Properties props = new Properties();
// 중요
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587"); //465, 587
props.put("mail.smtp.auth", "true");
// 추가 옵션
props.put("mail.smtp.quitwait", "false");
props.put("mail.smtp.socketFactory.port", "587");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "true");
props.put("mail.smtp.starttls.enable", "true");
try {
// 메일 세션 생성
Session session = Session.getDefaultInstance(props);
// 메일 송/수신 옵션 설정(1명 보내기)
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromEmail, fromUsername)); // 송신자(보내는 사람) 지정
message.addRecipient(RecipientType.TO, new InternetAddress(toEmail)); // 수신자(받는사람) 지정
message.setSubject(subject); // 이메일 제목 지정
// 메일 콘텐츠 설정
Multipart mParts = new MimeMultipart();
MimeBodyPart mTextPart = new MimeBodyPart();
// 인증번호 6자리 생성코드(영어 대/소문 + 숫자)
String cNumber = "";
for(int i=0 ; i< 6 ; i++) {
int sel1 = (int)(Math.random() * 3); // 0:숫자 / 1,2:영어
if(sel1 == 0) {
int num = (int)(Math.random() * 10); // 0~9
cNumber += num;
}else {
char ch = (char)(Math.random() * 26 + 65); // A~Z
int sel2 = (int)(Math.random() * 2); // 0:소문자 / 1:대문자
if(sel2 == 0) {
ch = (char)(ch + ('a' - 'A')); // 대문자로 변경
}
cNumber += ch;
}
}
// 메일에 출력할 텍스트
StringBuffer sb = new StringBuffer(); // 가변성 문자열 저장 객체
sb.append("<h3>[Community 프로젝트] 회원 가입 인증 번호입니다.</h3>\n");
sb.append("<h3>인증 번호 : <span style='color:red'>"+ cNumber +"</span></h3>\n");
//sb.append("<img src='https://cdn.wikifarmer.com/wp-content/uploads/2022/02/%ED%94%8C%EB%9F%BC%EB%B0%94%EA%B3%A0.jpg'>");
String mailContent = sb.toString(); // 문자열로 반환
// 메일 콘텐츠 - 내용 , 메일인코딩, "html" 추가 시 HTML 태그가 해석됨
mTextPart.setText(mailContent, "UTF-8", "html");
mParts.addBodyPart(mTextPart);
// 메일 콘텐츠 지정
message.setContent(mParts);
// MIME 타입 설정 (이메일 내용이 깨질 때 사용)
/*MailcapCommandMap MailcapCmdMap = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
MailcapCmdMap.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
MailcapCmdMap.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
MailcapCmdMap.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
MailcapCmdMap.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
MailcapCmdMap.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(MailcapCmdMap);*/
// 메일 발송
Transport t = session.getTransport("smtp");
t.connect(smtpEmail, password);
t.sendMessage(message, message.getAllRecipients());
t.close();
// -------------- 라이브러리 이용 -------------------
// 인증번호를 받은 이메일, 인증번호난수(cNumber), 인증번호 발급 시간(sysdate)
// -> DB '삽입->INSERT->행의 개수'
int result = new MemberService().insertCertification(inputEmail, cNumber);
resp.getWriter().print(result);
} catch (Exception e) {
e.printStackTrace();
// ajax error 속성 활용을 위한 500에러를 응답으로 전달.
resp.setStatus(500);
resp.getWriter().print(e.getMessage());
}
}
}
* resp.getWriter().print(result)
- resp: HttpServlerResponse 객체로 클라이언트로부터의 요청에 대한 응답
- getWriter(): 텍스트 데이터를 출력하기 위한 클래스인 PrintWriter 객체를 반환
- print(result): result의 값을 PrintWriter를 통하여 출력, 코드 HTTP 응답 본문에 result 변수 값을 출려 ㄱ
- 즉, 클라이언트에게 result 볌수의 값을 포함하는 HTTP 응답 전송
2. Service
package edu.kh.community.member.model.service;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import static edu.kh.community.common.JDBCTemplate.*;
import edu.kh.community.member.model.dao.MemberDAO;
import edu.kh.community.member.model.vo.Member;
public class MemberService {
private MemberDAO dao = new MemberDAO();
/** 인증번호 DB 추가 Service
* @param inputEmail
* @param cNumber
* @return
*/
public int insertCertification(String inputEmail, String cNumber) throws Exception{
Connection conn = getConnection();
//1. 입력한 이메일과 일치하는 값이 있으면(기존에 있음) 수정(UPDATE)
int result = dao.updateCertification(conn, inputEmail, cNumber);
//2. 입력한 이메일이 없으면(처음으로 발급) 삽입(INSERT)
if(result == 0) {
result = dao.insertCertification(conn, inputEmail, cNumber);
}
// DML 구문은 commit, rollback... 트랜잭션 제어 필요!!
if(result > 0) commit(conn);
else rollback(conn);
// 커넥션 반환
close(conn);
return result;
}
}
3. DAO
package edu.kh.community.member.model.dao;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import static edu.kh.community.common.JDBCTemplate.*;
import edu.kh.community.member.model.vo.Member;
//------------------------------------------
public class MemberDAO {
private Statement stmt;
private PreparedStatement pstmt;
private ResultSet rs;
private Properties prop;
public MemberDAO() {
try {
prop = new Properties();
String filePath = MemberDAO.class.getResource("/edu/kh/community/sql/member-sql.xml").getPath();
prop.loadFromXML( new FileInputStream(filePath) );
} catch(Exception e) {
e.printStackTrace();
}
}
/** 인증번호, 발급일 수정 DAO(result가 1일 때 UPDATE)
* @param conn
* @param inputEmail
* @param cNumber
* @return
*/
public int updateCertification(Connection conn, String inputEmail, String cNumber) throws Exception {
int result = 0;
try {
String sql = prop.getProperty("updateCertification");
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, cNumber);
pstmt.setString(2, inputEmail);
result = pstmt.executeUpdate(); // 업데이트가 이루어지면 1 or 0
} finally {
close(pstmt);
}
return result;
}
/** 인증번호 생성 DAO (result가 0이면 INSERT)
* @param conn
* @param inputEmail
* @param cNumber
* @return
*/
public int insertCertification(Connection conn, String inputEmail, String cNumber) throws Exception {
int result = 0;
try {
String sql = prop.getProperty("insertCertification");
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, inputEmail);
pstmt.setString(2, cNumber);
result = pstmt.executeUpdate();
} finally {
close(pstmt);
}
return result;
}
* XML
<!-- UPDATE: 이미 있는 이메일.. 인증번호, 발급일 수정 -->
<entry key="updateCertification">
UPDATE CERTIFICATION SET
C_NUMBER = ?,
ISSUE_DT = SYSDATE
WHERE EMAIL = ?
</entry>
<!-- INSERT: 인증번호 보내기 -->
<entry key="insertCertification">
INSERT INTO CERTIFICATION VALUES(?,?,SYSDATE)
</entry>
'Sever' 카테고리의 다른 글
5. 로그인 기능 구현하기 (1) | 2023.04.05 |
---|---|
4. JDBC - 연결 생성부터 자원반환까지 (0) | 2023.04.04 |
3. JDBC의 흐름 및 JDBC Tamplate (0) | 2023.04.04 |
2. JSP? + AJAX? (0) | 2023.03.28 |
1. Sevlet? (0) | 2023.03.27 |