220329 model2_ 로그인/아웃, 메인, 정보 수정/삭제
*** 회원관리
- 주요 기능
1. Connection Pool
2. request, session 객체 공유 설정 (로그인~로그아웃 동안 세션 영역)
3. Controller 클래스 : Java Servlet
4. Model = Service + DAO
Service, DTO, DAO 클래스
5. View ( 화면 인터페이스 ) : EL , JSTL 사용
* Service
- Action 인터페이스 : execute() 추상메소드를 오버라이딩해서 통일성 있게 구현하도록 함
ActionForward 클래스 -> 포워딩 방식, 포워딩 페이지명 설정
private boolean redirect; //포워딩 방식 (디스패치드, 리다이렉트) 설정
private String path; //포워딩 페이지명 설정
---> 각 setter, getter 생성.
(포워딩: 서블릿 프로그래밍 시 서블릿끼리, 혹은 서블릿과 JSP 사이에 정보를 공유하거나 정보를 전달하는 등의 연동 작업이 필요할 때 사용하는 기능)
- service 클래스 : 각 jsp파일에 대응되는 java 클래스 파일 --- 받은 값을 DAO로 넘겨주고 포워딩 방식 지정해 ActionForward로 넘겨주는 중간다리 역할
+ login
loginform.jsp : <form method="post" action="<%=request.getContextPath() %>/Login.do">
↓
MemberController.java : action = new Login(); forward = action.execute(request, response);
↓
Login.java -> DAO -> forward.setPath("./member/main.jsp"); 리턴
↓
MemberController.java : if(forward.isRedirect()) {}else {}
↓
main.jsp (View)
폼에서 받아온 값을 인코딩
request.setCharacterEncoding("utf-8");
DAO로 id, pw 넘기고 결과 리턴
int result=dao.login(id, passwd);
로그인 성공 시, 세션 영역으로 id 값 공유 설정 ★
HttpSession session = request.getSession(); //session 객체 생성★
session.setAttribute("id", id); //session 영역으로 id값 공유
-> 조건문 빠져나와 main.jsp으로 forward path 지정
forward.setRedirect(false); //성공 시 조건문 나와서 이쪽으로~
forward.setPath("./member/main.jsp");
return forward;
로그인 실패 시, 팝업 메시지가 뜨고 뒤로가기 해야 함★
<script> 코드 사용 필요 -> 출력스트림 out 객체 생성 후 <script> 적용할 것.
PrintWriter out=response.getWriter(); //출력스트림 객체 생성
out.println("<script>");
out.println("alert('로그인 실패');");
out.println("history.go(-1);");
out.println("</script>");
out.close();
return null; //실패 시 리턴값 없이 로그인창으로 되돌아감
+) 팝업 메시지, 화면 출력 등의 글자가 깨지는 경우 : 현재 문서의 값을 인코딩해야 함!
(((response와 request의 인코딩 차이)))
response.setContentType("text/html; charset=UTF-8"); //현재 문서의 글자가 깨지지 않도록 인코딩
request.setCharacterEncoding("utf-8"); //외부에서 받아온 글자가 깨지지 않도록 인코딩
---> 즉 현재 페이지에 한글을 입력한 상태에서는 둘 다 넣어주는 게 좋음
+ main
세션 존재할 때 (로그인 상태)
<c:if test="${sessionScope.id != null }">
or <c:if test="${!empty sessionScope.id }">
정보 수정, 로그아웃, 회원 탈퇴 메뉴 뜨도록 처리
세션 존재하지 않을 때 (default)
<c:if test="${sessionScope.id == null }">
or <c:if test="${empty sessionScope.id }">
회원 가입, 로그인 메뉴 뜨도록 처리
각 메뉴의 링크는 controller로 넘어갈 수 있도록 *.do 형식으로 넘기고, controller에서 제어할 수 있도록 처리.
<a href="<%=request.getContextPath() %>/MemberForm.do">회원가입 <br></a>
-> 이후 controller에서 포워드할 페이지 경로를 지정 -> 해당 페이지로 넘어가게 됨
+) getContextPath() 사용해야 하는 이유 : uri 경로를 제대로 잡아주기 위함
+logout
: db 연동 없이 세션만 해제하면 되므로 service 클래스 불필요 -> controller에서 바로 forward 지정
곧바로 세션 삭제
session.invalidate();
---> 세션 영역으로 값이 공유되는 상태이므로(member 폴더 내에서), 새로 세션 객체를 생성하고 값을 가져오는 과정을 반복할 필요가 없음
로그아웃 팝업 메시지 출력 후 메인으로 넘어갈 수 있게 controller로 돌아감
location.href="./Main.do";
+update
1차 처리 (폼 이전)
main.jsp : <a href="<%=request.getContextPath() %>/UpdateMember.do">
↓
MemberController.java : action = new UpdateMember(); forward = action.execute(request, response);
↓
UpdateMember.java -> DAO 회원 정보 가져와 DTO에 저장 -> forward.setPath("./member/updateform.jsp"); 리턴
↓
MemberController.java : if(forward.isRedirect()) {}else {}
↓
updateform.jsp (View) -> 폼에 가져온 상세정보가 적용되어 나타남
service 클래스이므로 session 영역에 공유되는 값을, session 객체를 생성해서 getAttribute("id") 메소드로 구해와야 함! ---> object형이기 때문에 String형으로 강제형변환(다운캐스팅)해줌
String id=(String)session.getAttribute("id");
DAO로 넘겨서 처리 후 DTO로 받아옴
member=dao.getMember(id);
다중선택 가능한 옵션을 위해(checkbox) 문자열로 붙어있는 값을 구분자 기준으로 나눠 배열에 저장
String[] h=member.getHobby().split("-");
DTO와 배열에 저장한 값을 request 영역으로 공유 설정
request.setAttribute("member", member);
request.setAttribute("h", h);
update.jsp로 넘겨서 수정 폼에 출력되도록 함 --->★ request영역으로 DTO를 공유하므로 dispatcher 방식 사용
2차 처리 (폼 이후)
updateform.jsp (View)
↓
MemberController.java : action = new Update(); forward = action.execute(request, response);
↓
Update.java -> DAO 회원 정보 가져와 DTO에 저장 -> forward.setPath("./member/main.jsp"); 리턴
↓
MemberController.java : if(forward.isRedirect()) {}else {}
↓
main.jsp (View)
updateform.jsp (View)
유효성 검사가 잘 되지 않을 때 -> js파일의 경로를 다시 설정할 것. (./member/member.js)
특별히 수정이 필요하지 않은 항목은 hidden으로 함께 전달할 수 있도록 처리할 것.
<input type='hidden' id='id' name='id' value=" ${member.id }"/>
updateform.jsp에 1차 처리에서 request영역으로 공유 설정한 값을 가져올 때, EL(JSTL) 이용
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
${member.id} <-- 이런 형식으로 공유 값을 바로 사용할 수 있음!
같은 동작하는 다른 코드
<%
MemberDTO mem=(MemberDTO)request.getAttribute("member");
%>
<%=mem.getId() %>
--------> 즉 JSTL이 훨씬 간단하므로 View에는 되도록 이걸 사용할 수 있게 해야 함.
- select option
core의 if 태그를 이용해 공유된 DB값이 옵션값과 같은지 비교하고, 일치하는 경우 그 옵션을 선택 처리함
<c:if test="${member.phone1=='010' }"> ${'selected' } (그냥 selected 로 써도 무방)</c:if>
- radio
core의 if 태그를 이용해 공유된 DB값이 옵션값과 같은지 비교하고, 일치하는 경우 그 옵션을 선택 처리함
<c:if test="${member.gender=='남자' }">${'checked' } (그냥 checked 로 써도 무방)</c:if>
- checkbox ★
jquery (+JSTL)로 처리 : 반복문으로 DTO 배열을 돌려서 일치하는 값이 있을 경우 그 옵션을 선택 처리함
유효성 검사하는 head 부분에 스크립트를 추가!
$(document).ready(function(){
<c:forEach var="s" items="${h}"> //request로 공유한 값(리스트, 배열)을 item에 넣어서 변수 s에 저장함
$("input:checkbox[name='hobby'][value='${s}']").attr("checked","true");
//input 중 checkbox 태그를 구함 -> 필터: name='hobby'이고 value=${s}여야 함 (내가 선택한 옵션)
//필터에 해당되는 옵션에 .attr("checked","true")조건을 추가함
</c:forEach>
});
- textarea : value 속성 말고 태그 사이에 기입 (기입 시 줄바꾸지 말 것)
Update.java
받아온 값을 인코딩
request.setCharacterEncoding("utf-8");
DTO 객체 생성 후 폼에서 request로 공유된 값을 저장
MemberDTO member=new MemberDTO();
member.setId(request.getParameter("id")); ........
(hobby는 배열을 구분자를 포함한 하나의 문자열로 합쳐 저장할 것)
기존 DB에 저장되어있던 비밀번호와 폼에 입력한 비밀번호를 비교해 일치할 경우 update 진행
if(old.getPasswd().equals(member.getPasswd())) {
int result=dao.updateMember(member);
} else {
비밀번호 불일치 시 출력될 부분
}
위의 출력 부분은 출력스트림 out 객체를 생성 -> 팝업 메시지를 띄울 수 있도록 처리
PrintWriter out=response.getWriter();
if(old.getPasswd().equals(member.getPasswd())) { //폼에 적은 비번과 일치하는지 확인 int result=dao.updateMember(member); if(result==1) { out.println("<script>"); out.println("alert('수정되었습니다.');"); out.println("</script>"); } } else { out.println("<script>"); out.println("alert('비밀번호가 일치하지 않습니다.');"); out.println("histort.go(-1);"); out.println("</script>"); return null; //forward하지 않고 되돌아갈 수 있도록 반드시! 처리해줘야 함 } |
+Delete
main.jsp : <a href="<%=request.getContextPath() %>/DeleteMember.do">
↓
MemberController.jsp : forward.setPath("./member/deleteform.jsp");
↓
deleteform.java : (DAO에서 값 받아온적 없으니) 기존에 session영역으로 공유된 id값 ${sessionScope.id} , 입력받은 passwd값을 받아 service 클래스로 넘김 -> action="<%=request.getContextPath() %>/Delete.do"
↓
MemberController.java : action = new Delete();
↓
Delete.java : id, passwd 값 받아놓고, DB에 저장된 비번과 입력받은 비번이 일치할 경우 id를 DAO로 넘겨서 삭제 처리 + 세션 공유 삭제 + 메인으로 돌아가기 forward.setPath("/Main.do");
↓
MemberController.java : forward.setPath("./member/main.jsp");
↓
main.jsp (View)