1) mailForm
2)mailSend를 위한작업
3)비밀번호수정 password
4)아이디찾기 비밀번호찾기 id , pw
5) 사진등록 picutreForm
1) mailForm
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>
layout.jsp에 head부분script에 넣어줬음 ( 메일폼을 위해)
webapp\view\member\mailForm.jsp
(그냥구글비번이 아닌 앱비밀번호(2차인증)으로 로그인하자!!!!)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript">
function inputchk(f) {
if(f.googleid.value==""){
alert("구글아이디입력바람");
f.googleid.focus();
return false;
}
if(f.googlepw.value==""){
alert("구글비번을 입력하세요")
f.googlepw.focus();
return false;
}
return true;
}
</script>
<title>메일작성</title>
</head>
<body>
<div class="container"></div>
<h2 id="center">메일보내기</h2>
<form action="mailSend" method="post" name="form1" onsubmit="return inputchk(this)">
<table class="table">
<tr><td>보내는사람</td>
<td>본인구글ID:<input type="text" name="googleid" class="form-control" value="ddkk8525">
본인구글PW:<input type="password" name="googlepw" class="form-control" value="muefnfldrbqlbfez"></td>
</tr>
<tr><td>받는사람</td>
<td><input type="text" name="recipient" class="form-control"
value="<c:forEach items="${list}" var="m">${m.name} <${m.email}></c:forEach>">
<%-- name <email> 의 형태로 check된member가 나열될거임 --%>
</td></tr>
<tr><td>제목</td>
<td><input type="text" name=title class="form-control"></td>
</tr>
<tr><td>메시지형식</td>
<td><select name="mtype" class="form-control">
<option value="text/html;charset=UTF-8">HTML
<option value="text/plain;charset=UTF-8">TEXT
<!-- plane : 순수한 text파일이라는뜻(태그인식X) -->
</select></td>
</tr>
<tr><td colspan="2">
내용:<textarea name="content" rows="10" cols="40" class="form-control"></textarea></td></tr>
<tr><td colspan="2" id="center">
<button type="submit" class="btn btn-primary">전송</button></td></tr>
</table>
</form>
</body>
</html>
MemberDto 에 emailList 메서드
public List<Member> emailList(String[] ids) {
//ids : 선택한 아이디목록 "[test1 test2]"
Connection conn = DBConnection.getConnection();
PreparedStatement psmt = null;
ResultSet rs = null;
ArrayList<Member> list = new ArrayList<Member>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ids.length; i++) {
sb.append("'"+ids[i]+((i<ids.length -1)?"',":"'"));
//마지막인덱스라면 , 를안찍음(sql에넣기위함)
}//sb = 'test1','test2'....
String sql = "select * from member where id in("+ sb.toString()+")";
//sb를 String으로변경 id in('id1' , 'id2'..)
try {
psmt = conn.prepareStatement(sql);
rs = psmt.executeQuery();
while(rs.next()) {
Member m = new Member();
m.setId(rs.getString("id"));
m.setName(rs.getString("name"));
m.setPass(rs.getString("pass"));
m.setGender(rs.getInt("gender"));
m.setEmail(rs.getString("email"));
m.setTel(rs.getString("tel"));
m.setPicture(rs.getString("picture"));
list.add(m);
}
return list;
}
catch (Exception e) {
e.printStackTrace();
}
finally {
DBConnection.close(conn, psmt, rs);
}
return null;
}
MemberController 의 mailForm매핑(선택된 아이디의 객체를 속성으로지정해준후 mailForm이동)
@RequestMapping("mailForm")
@MSLogin("loginAdminCheck") //관리자만가능
public String mailForm(HttpServletRequest request, HttpServletResponse response) {
//관리자로 로그인시에만 실행
String[] ids = request.getParameterValues("idchk");//해당파라미터의 값들을 배열로리턴
System.out.println(Arrays.toString(ids));
List<Member> list = dto.emailList(ids);
System.out.println(list);
request.setAttribute("list", list);
return "member/mailForm";
}


2) mailSend를 위한 작업들
구글 smtp서버 이용해 메일전송하기
1.구글계정에 접속해 2단계 로그인설정하기
2.앱비밀번호 생성
3.생성된 앱 비번을 메모장을 이용해저장하기
4. mail.properties 파일 /web-inf/에 만들기
5. 라이브러리 가져오기



/webapp\WEB-INF\mail.properties
# gmail !!!
#smtp : 이메일을 주고받기 위해 사용되는 인터넷 표준 프로토콜
mail.smtp.host=smtp.gmail.com
mail.smtp.starttls.enable=true
mail.debug=true
mail.smtp.auth=true
mail.smtp.port=587
mail.smtp.ssl.protocols=TLSv1.2
공백조심해!!!!
Cotroller에 MyAtuthenticator 생성 (id pw를 이용한 사용자인증 이라고생각해두자)
//사용자 이름과 비밀번호를 저장하고, Session 객체가 이를 활용하여
//안전하게 이메일 서버에 연결할 수 있도록 합니다
public final class MyAuthenticator extends Authenticator{
private String id;
private String pw;
public MyAuthenticator(String id, String pw) {
this.id = id;
this.pw = pw;
}
protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
return new javax.mail.PasswordAuthentication(id, pw);
}
}
Controller의 mailSend 메서드
( mail부분에서 가장중요하다고보면 됨) 주석을 하나하나 다 읽어보자
@RequestMapping("mailSend")
@MSLogin("loginAdminCheck") //관리자만가능
public String mailSend(HttpServletRequest request, HttpServletResponse response) {
String sender = request.getParameter("googleid") + "@gmail.com";
//작성자의아이디에 @gmail.com을붙임
//앱비밀번호
String passwd = request.getParameter("googlepw");
//recipient : mem.name , mem.email 형식의 String
//(선택한 아이디의 이름과 이메일만 들어있음)
String recipient = request.getParameter("recipient");
String title = request.getParameter("title");
String mtype = request.getParameter("mtype");
String result="메일전송실패";
String content = request.getParameter("content");
Properties prop = new Properties();//이메일전송위한 환경설정값
try {
String path = request.getServletContext().getRealPath("/") //내프로젝트의절대경로
+"WEB-INF/mail.properties"; //해당파일사용
FileInputStream fis = new FileInputStream(path); //파일을읽어
prop.load(fis);//fis가 참조하는 파일의내용을 Properties객체의요소로저장
prop.put("mail.smtp.user", sender);//전송하는 사람의 이메일주소
}
catch (Exception e) {
e.printStackTrace();
}
//메일전송을 위한 사용자인증(연결)객체
MyAuthenticator auth = new MyAuthenticator(sender, passwd);
//prop : 메일전송을위한 시스템환경설정 (mail.properties)
//auth : 인증객체
Session mailSession = Session.getInstance(prop,auth);
//msg : 메일로전송되는 데이터객체
MimeMessage msg = new MimeMessage(mailSession);
//이메일주소들을 담을수있는 리스트
ArrayList<InternetAddress> addrs = new ArrayList<InternetAddress>();
try {
//recipient는 name,email,name2,email2 형식의 String임.
String[] emails = recipient.split(",");
for (String email : emails) { //email : 이름 or email
try {
//email.getBytes("UTF-8") : byte배열
//8859_1 : 웹의 기본인코딩방식
//addrs에는 이메일형식만 들어갈거야(이름은들어가지않음)
addrs.add(new InternetAddress(
new String(email.getBytes("UTF-8"),"8859_1")));
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
InternetAddress[] address = new InternetAddress[emails.length];
for (int i = 0; i < addrs.size(); i++) {
//setRecipients는 List를 받지못하고 배열만 받기때문!!
//mail API는 오래되서그렇다!
address[i] = addrs.get(i);
}
InternetAddress from = new InternetAddress(sender);
msg.setFrom(from); //보내는사람의 이메일주소
//address의 이메일에게 메일 보낸단 뜻
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject(title);
msg.setSentDate(new Date());
msg.setText(content);
//multipart : 내용,첨부파일1,.....
MimeMultipart multipart = new MimeMultipart();
MimeBodyPart body = new MimeBodyPart();
body.setContent(content,mtype); //내용
multipart.addBodyPart(body);
msg.setContent(multipart);
Transport.send(msg); //메일전송
result = "메일전송완료";
}
catch (MessagingException e) {
e.printStackTrace();
}
request.setAttribute("msg", result);
request.setAttribute("url", "list");
return "alert";
}
테스트
(pw는 아까 발급받은 앱비밀번호16자리를 공백없이 해보자!)


HTML전송


3) 비밀번호수정 (info에서 시작됨)
/view/member/passwordForm.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="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
</head>
<body>
<h3>비밀번호변경</h3>
<form action="password" method="post" name="f" onsubmit="return input_check(this)">
<table class="table">
<tr><th>현재 비밀번호</th>
<td><input type="password" name="pass" class="form-control"></td></tr>
<tr><th>변경 비밀번호</th>
<td><input type="password" name="chgpass" class="form-control"></td></tr>
<tr><th>재입력</th>
<td><input type="password" name="chgpass2" class="form-control"></td></tr>
<tr><td colspan="2" align="center">
<input type="submit" value="비밀번호변경" class="btn btn-primary">
<input type= "reset" value="초기화" class="btn btn-secondary"></td></tr>
</table>
</form>
<script type="text/javascript">
function input_check(f){
if(f.chgpass.value != f.chgpass2.value){
alert("변경할비밀번호 제대로 재입력하세요");
f.chgpass2.value="";
f.chgpass2.focus();
return false;
}
return true;
}
</script>
</body>
</html>
로그인하지않고 접근 시 loginForm으로 보내버리는 함수
public String passwordLoginCheck(HttpServletRequest request, HttpServletResponse response) {
String login = (String)request.getSession().getAttribute("login");
if(login == null || login.trim().equals("")){
request.setAttribute("msg", "로그인하세요");
request.setAttribute("url", "loginForm");
return "alert";
}
return null;
}
(null은 신경쓰지마 )
Controller의 passwordForm매핑
passwordLoginCheck함수를 이용해
로그인을 한 사람이 접근 시 passwordForm으로 정상적으로보내줌
@RequestMapping("passwordForm")
@MSLogin("passwordLoginCheck")
public String passwordForm(HttpServletRequest request, HttpServletResponse response) {
return "member/passwordForm";
}
Controller의 password 메서드 (passwordForm에서 찾기버튼 누를 시 발생)
@RequestMapping("password")//비밀번호변경부분
@MSLogin("passwordLoginCheck")
public String password(HttpServletRequest request, HttpServletResponse response) {
String login = (String)request.getSession().getAttribute("login");
String pass = request.getParameter("pass");//입력비번
String chgpass = request.getParameter("chgpass");//변경비번
Member mem = dto.selectOne(login);
//select * from member where id='login값'
//입력한비밀번호와 DB상의비번이 같다면
if(pass.equals(mem.getPass())) {
if(dto.updatePass(login, chgpass)) {
request.setAttribute("msg", "성공(새로운비번으로 로그인_");
request.setAttribute("url", "logout");
return "openerAlert";
}
else { // 비밀번호는 맞지만 DB내에서문제 생길 시
StringBuilder sb =new StringBuilder();
sb.append("alert('비밀번호수정시오류가발생했습니다.')");
request.setAttribute("script", sb.toString());
return "dumy";
}
}else { //비밀번호를 틀렸을 시
request.setAttribute("msg", "비밀번호가틀려요");
request.setAttribute("url", "passwordForm");
return "alert";
}
}
view / openAlert.jsp
(opener 의 경로를 바꿔준 후
내 자신의 창을 닫는다)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script>
alert("${msg}");
opener.location.href = "${url}";
self.close();
</script>
view / dumy
(script 속성만 호출하는 곳 (페이지가없음))
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script>
${script}
</script>
4)아이디찾기 비밀번호찾기 조금의수정(화면)
id찾기
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<title>idForm(아이디찾기)</title>
</head>
<body>
<h3 align="center">아이디찾기</h3>
<form action="id" method="post" >
<table class="table">
<tr><th>이름</th><td><input type="text" name="name" class="form-control"></td></tr>
<tr><th>전화번호</th><td><input type="text" name="tel" class="form-control"></td></tr>
<tr><td colspan="2"><input type="submit" value="아이디찾기" class="btn btn-outline-info"></td></tr>
</table></form>
</body>
</html>
pw찾기
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%-- /webapp/member/pwForm.jsp--%>
<!DOCTYPE html>
<html>
<!-- 비밀번호찾기버튼 클릭시 유효성검사 실시 추가 -->
<head>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<meta charset="UTF-8">
<title>비밀번호찾기</title>
</head><body><h3 align="center">비밀번호찾기</h3>
<form action="pw" method="post" onsubmit="return input_check(this)">
<table class="table">
<tr><th>아이디</th><td><input type="text" name="id" class="form-control"></td></tr>
<tr><th>이메일</th><td><input type="text" name="email" class="form-control"></td></tr>
<tr><th>전화번호</th><td><input type="text" name="tel" class="form-control"></td></tr>
<tr><td colspan="2"><input type="submit" value="비밀번호찾기" class="btn btn-light"></td></tr>
<!-- submit을 누르면 pw로 넘어간다 -->
</table>
</form></body>
<script>
function input_check(f){
if(f.id.value.trim() == ""){
alert("ID입력바람")
return false;
}
else if(f.email.value.trim() == ""){
alert("Email입력바람")
return false;
}
else if(f.tel.value.trim() == ""){
alert("전화번호입력바람")
return false;
}
else if(!isValidEmail(f.email.value.trim())){
alert("올바르지않은 이메일형식")
f.email.focus()
return false;
}
else if(!isValidTel(f.tel.value.trim())){
alert("올바르지않은 전화번호형식")
f.tel.focus()
return false;
}
else{
return true;
}
function isValidEmail(email){
const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9._]+\.[a-zA-Z]{2,}$/;
return regex.test(email);
/*
/^ .... $/ => 정규표현식 시작과 끝
[a-zA-Z0-9._%+-]+ : 대소문자 숫자 . - % + - 중 1개이상
@[a-zA-Z0-9._]+ : @ 문자뒤에 대소문자 숫자. _ 중 한개이상
\. : .문자
[a-zA-Z]{2,} : 대소문자 2개이상
*/
}
function isValidTel(tel){
const regex = /^(02|01[0126789])-?\d{3,4}-?\d{4}$/;
return regex.test(tel);
/*
(02|01[0126789]) : 02 or 010 011 ...019
-? : - 가 0 또는 1개
\d{3,4} : 숫자 3개or4개
\d{4} : 숫자4개
*/
}
}
</script>
</html>
id , pw 의 Controller부분
@RequestMapping("id")
public String id(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
String name = request.getParameter("name");
//name="name"인 파라미터를 가져와
//charEncodingFilter를 만들어놨으므로 인코딩이필요없음
String tel = request.getParameter("tel");
String id = dto.idSearch(name, tel);
//MemberDto에 가서 DB정보와비교해 가져온다
if(id==null) {
request.setAttribute("msg", "id를 찾을수없어요");
request.setAttribute("id", id);
return "idSearch";
}
else {
request.setAttribute("msg", name+"님의 id : "+id.substring(0,id.length()-2)+"**");
request.setAttribute("id", id);
return "idSearch";
}
}
@RequestMapping("pw")
public String pw(HttpServletRequest request, HttpServletResponse response) {
String id = request.getParameter("id");
//name="name"인 파라미터를 가져와
String email = request.getParameter("email");
String tel = request.getParameter("tel");
String pass = dto.pwSearch(id, tel, email);
//MemberDto에 가서 DB정보와비교해 가져온다
if(pass==null) {
request.setAttribute("msg", "password를 찾을수없어요");
request.setAttribute("pass", pass);
return "pwSearch";
}
else {
request.setAttribute("msg", id+"님의 password : "+pass.substring(0,pass.length()-2)+"**");
request.setAttribute("pass", pass);
return "pwSearch";
}
}
idSearch , pwSearch
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script>
alert("${msg}")
//requestScope.msg
opener.document.f.id.value = "${id}"
//requestScope.id
self.close();
</script>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script>
alert("${requestScope.msg}")
opener.document.f.pass.value = "${requestScope.pass}"
//request영역의 속성인 msg , pass
self.close();
</script>
5)picture 수정 , 등록
/view/pictureForm.jsp(수정 or 등록하는곳)
수정 시 opener : updateForm
등록시 opener : joinForm
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원사진등록</title>
</head>
<body>
<table>
<tr><td><img id="preview" src=""></td></tr>
<tr><td>
<!-- MIME 타입 :문서의 형식설정 문서유형/세부종류 text/html , img/jpeg , img/gif...
accept = "img/*" img문서유형만 업로드한단 뜻
-->
<form action="picture" method="post" enctype="multipart/form-data"><!-- 파일을 보내기위함 -->
<input type="file" name="picture" id="imageFile" accept="img/*">
<input type="submit" value="사진등록">
</form></td></tr>
</table>
<script type="text/javascript">
let imagefile = document.querySelector('#imageFile');
let preview = document.querySelector('#preview');
//파일이('change') 바뀌었을 때 발생하는 이벤트
imagefile.addEventListener('change',function(e){
//선택된파일을 담는 변수
//e.target.files : 선택된파일들
let get_file = e.target.files;
let reader = new FileReader(); //파일을 읽기위한 스트림객체
//reader객체에 파일이 로드되는경우 이벤트등록
//Img매개변수 : preview객체를 저장
//자바스크립트에서는 함수객체를 리턴할수있음
reader.onload = (function(Img){
//preview(이미지태그)를 매개변수로하는 함수호출
return function(e){
//e.target.result: 선택된파일의value값(파일명)
Img.src = e.target.result;
}
})(preview); // Img = preview
//get_file : 선택된파일이존재하는가?
//reader.readAsDataURL(get_file[0]) :
//첫번쨰선택된 파일을 reader로 읽기
if(get_file){reader.readAsDataURL(get_file[0]);}
});
</script>
</body>
</html>
(submit하면 넘어가는)Picutre Controller
C:\java\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\model2Study\picture
해당경로에 업로드되고
해당경로에서 사진을 가져오게될것임!!!!!
@RequestMapping("picture")
public String picture(HttpServletRequest request, HttpServletResponse response) throws IOException {
String path = request.getServletContext().getRealPath("")+"/picture/";
//기준 디렉토리 의 실제 경로
//C:\java\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\model2Study\picture
String fname = null;
File f = new File(path);//업로드되는 폴더정보
if(!f.exists()){
f.mkdirs(); //없으면 폴더생성
}
//request : 이미지데이터저장
//path : 업로드되는 폴더정보
//10*1024*1024 : 최대업로드크기(10M)
//new DefaultFileRenamePolicy() : 중복파일명존재시 이름변경해
MultipartRequest multi = new MultipartRequest(
request,path,10*1024*1024,"UTF-8",new DefaultFileRenamePolicy());
fname = multi.getFilesystemName("picture");//사진명
request.setAttribute("fname", fname);
return "pic";
}
pic.jsp (picture controller가 호출하는 곳)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<script>
img = opener.document.getElementById("pic");//id="pic" ..이미지객체임
img.src = "${pageContext.request.contextPath}/picture/${fname}";
/*form하위의 name=picture인 값에(type=hidden) 넣어라
* DB에 경로를 전부다 넣기에는 길다.
*/
opener.document.f.picture.value = "${fname}";
//self : 현재페이지
self.close();//창을 닫는다
</script>
updateForm의 name="picture" 와 img.src부분
<input type="hidden" name="picture" value="${mem.picture}">
<img src="${pageContext.request.contextPath}/picture/${mem.picture}>" width="100" height="120" id="pic"><br>
list 의 src부분만 남겨놓겠음 (사진이보여지는부분)
2025.04.11 - [JSP] - 부트캠프49일차(model2 {login ,main ,info ,update,delete,list,layout
부트캠프49일차(model2 {login ,main ,info ,update,delete,list,layout
1) login2)main3)info4)update5)delete6)list(목록)7)sitemesh , layout 1) memberController에 login구현 package controller;import javax.servlet.annotation.WebInitParam;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServletRequest
ddkk1120.tistory.com
여기에 자세한코드있음
</tr>
<c:forEach var="mem" items="${list}"> <%--멤버객체가있는 list --%>
<tr>
<!-- mem.xx : getxx프로퍼티 -->
<td><a href="info?id=${mem.id}">${mem.id}</a></td>
<td><img src="${pageContext.request.contextPath}/picture/${mem.picture}" width="30" height="30"></td>
<!--../picture/${mem.picture} 로 해도됨 ( url을 잘보자) -->
<!--C:/java/workspace/.metadata/.plugins/org.eclipse.wst.server.core
/tmp0/wtpwebapps/model2Study/picture/ -->
절대경로 "${pageContext.request.contextPath}/picture/${mem.picutre}";
하지만
src는 ../picture/${ mem.picutre } 으로해도 무관하다
하지만 제발 URL을 잘 확인하자
../picture/${ mem.picutre } (상대경로) 사용 시


http://localhost:8080/model2Study/member/member/list
다음과같다면(../../을 사용하면해결은 될것이다 절대경로는 상관없음) 나오지않을것이고
http://localhost:8080/model2Study/member/list
다음과같이 변경시 정상적으로 상대경로가 작동할거다


'JSP' 카테고리의 다른 글
부트캠프52일차(framwork설명,동적쿼리,인터페이스이용한Mapper , model2Study 리팩토링) (0) | 2025.04.16 |
---|---|
부트캠프51일차 (model2 idchk) , (MyBatis시작 , 세팅법 사용법) (0) | 2025.04.15 |
주말 (49일차에 이어짐 id.pw찾기 , loginForm관련 , picture절대경로만들기) (0) | 2025.04.12 |
부트캠프49일차(model2 {login ,main ,info ,update,delete,list,layout (1) | 2025.04.11 |
부트캠프48일(core태그 , fmt태그 , fn태그 , model2시작) (0) | 2025.04.10 |