[포스코DX|Cookie|5주] 23일차 수업
포스코DX X 비트교육센터 6기 - Cookie
mysite02 : servlet + JSP
UserController 와 req/res
req1 : /user?a=joinform
- 네비게이션의 메뉴에서 버튼 클릭시, joinform으로 넘어감. req2 : /user?a=join
- 회원가입 페이지에서 정보를 입력하고, 확인을 눌렀을 때의 경로로 ```java ``` - userController에 ```java if("joinform".equals(action)) { request.getRequestDispatcher("/WEB-INF/views/user/joinform.jsp").forward(request, response); } else if("join".equals(action)) { String name = request.getParameter("name"); String email = request.getParameter("email"); String password = request.getParameter("password"); String gender = request.getParameter("gender"); //데이터 전달의 확인 //System.out.println(name + " : " + email + " : " + password + " : " + gender); } ``` - db에 user Table 추가 ```sql create table user( no int not null auto_increment, name varchar(45) not null, email varchar(200) not null, password varchar(64) not null, gender enum('female', 'male') not null, join_date date not null, primary key(no) ); ``` - userVo 만들기. - userController에 추가 ```java UserVo userVo = new UserVo(); userVo.setName(name); userVo.setEmail(email); userVo.setPassword(password); userVo.setGender(gender); new UserDao().insert(userVo); ``` - userDao의 insert를 추가하기 ```java public void insert(UserVo vo) { Connection conn = null; PreparedStatement pstmt = null; try { conn = getConnection(); String sql = "insert into user values(null, ?,?, password(?), ?, current_date())"; pstmt = conn.prepareStatement(sql); pstmt.setString(1, vo.getName()); pstmt.setString(2, vo.getEmail()); pstmt.setString(3, vo.getPassword()); pstmt.setString(4, vo.getGender()); pstmt.setString(5, vo.getJoinDate()); pstmt.executeQuery(); } catch (SQLException e) { System.out.println("error:" + e); } finally { try { if(pstmt != null) { pstmt.close(); } if(conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } ```res. redirect:/user?a=joinsuccess (join이 완료 되었다는 응답으로 이동시켜준다.) + req3. /user?a=joinsuccess
ex. LOgin 후 메인페이지 ex. join(회원가입) 후 가입 성공 축하 페이지 > userController에서 리다이렉트 추가해주기 ```java // 앞 부분 생략 UserVo userVo = new UserVo(); userVo.setName(name); userVo.setEmail(email); userVo.setPassword(password); userVo.setGender(gender); new UserDao().insert(userVo); response.sendRedirect(request.getContextPath() + "/user?a=joinsuccess"); }else if("joinsuccess".equals(action)) { request.getRequestDispatcher("/WEB-INF/views/user/joinsuccess.jsp").forward(request, response); } ``` > joinsuccess.html -> jsp파일로 ```java <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html>controller의 action에 따른 작동들을 단순하고 편하게 만들어보자. (컴포넌트를 쪼개보자!)
- 간단히 하고자 하는 것. (추상화, 객체지향으로 분리 시킬 것이다.) ```java // String name = request.getParameter("name"); // String email = request.getParameter("email"); // String password = request.getParameter("password"); // String gender = request.getParameter("gender"); // // //데이터 전달의 확인 // //System.out.println(name + " : " + email + " : " + password + " : " + gender); // // UserVo userVo = new UserVo(); // userVo.setName(name); // userVo.setEmail(email); // userVo.setPassword(password); // userVo.setGender(gender); // // new UserDao().insert(userVo); ``` - web/mvc 패키지 추가하기.   앞으로, guestbook이 추가되면, guestbook 패키지를 추가하고, indexActon, AddAction, DeleteFormAction, DeleteAction이 추가 될 것이다.  - 패키지와 class를 추가하기  - userController에서 이렇게 바꾼다. ```java package com.poscodx.mysite.controller; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.ant.jmx.JMXAccessorQueryTask; import com.poscodx.mysite.dao.UserDao; import com.poscodx.mysite.vo.UserVo; import com.poscodx.web.mvc.Action; import com.poscodx.web.mvc.user.JoinAction; import com.poscodx.web.mvc.user.JoinFormAction; import com.poscodx.web.mvc.user.JoinSuccessAction; public class UserController extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String actionName = request.getParameter("a"); Action action = null; if ("joinform".equals(actionName)) { action = new JoinFormAction(); } else if ("join".equals(actionName)) { action = new JoinAction(); } else if ("joinsuccess".equals(actionName)) { action = new JoinSuccessAction(); } if(action==null) { //뭔갈 누른게 아니고, url을 사용자가 치고 들어온 경우. response.sendRedirect(request.getContextPath()); //return 까먹지 말기. return; } action.execute(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ``` - Action.java ```java package com.poscodx.web.mvc; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface Action { public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; } ``` - jsp로 이동시켜주는 애들도 분리 ```java package com.poscodx.web.mvc.user; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.poscodx.web.mvc.Action; public class JoinFormAction implements Action { @Override public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { request.getRequestDispatcher("/WEB-INF/views/user/joinform.jsp").forward(request, response); } } ``` ```java package com.poscodx.web.mvc.user; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.poscodx.web.mvc.Action; public class JoinSuccessAction implements Action { @Override public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { request.getRequestDispatcher("/WEB-INF/views/user/joinsuccess.jsp").forward(request, response); } } ``` - joinAction.jsp - join실행시 작동되는 문들도 뽀개기!!! ```java package com.poscodx.web.mvc.user; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.poscodx.mysite.dao.UserDao; import com.poscodx.mysite.vo.UserVo; import com.poscodx.web.mvc.Action; public class JoinAction implements Action { @Override public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String name = request.getParameter("name"); String email = request.getParameter("email"); String password = request.getParameter("password"); String gender = request.getParameter("gender"); //데이터 전달의 확인 //System.out.println(name + " : " + email + " : " + password + " : " + gender); UserVo userVo = new UserVo(); userVo.setName(name); userVo.setEmail(email); userVo.setPassword(password); userVo.setGender(gender); new UserDao().insert(userVo); response.sendRedirect(request.getContextPath() + "/user?a=joinsuccess"); } } ```ActionFactory
 - mainController도 이제 이쁘게 만들기 ```java package com.poscodx.mysite.controller; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.poscodx.mysite.web.mvc.main.MainActionFactory; import com.poscodx.web.mvc.Action; import com.poscodx.web.mvc.user.UserActionFactory; public class MainController extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String actionName = request.getParameter("a"); Action action = new MainActionFactory().getAction(actionName); action.execute(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ``` - mainActionFactory ```java package com.poscodx.mysite.web.mvc.main; import com.poscodx.web.mvc.Action; import com.poscodx.web.mvc.ActionFactory; public class MainActionFactory implements ActionFactory { @Override public Action getAction(String actionName) { return new MainAction(); } } ``` - mainAction ```java package com.poscodx.mysite.web.mvc.main; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.poscodx.web.mvc.Action; public class MainAction implements Action { @Override public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { request .getRequestDispatcher("/WEB-INF/views/main/index.jsp") .forward(request, response); } } ``` - 이제는 서블릿 작업을 하는 것이 아니라, 각각의 핸들러들을 이용하여 수정하면 된다. (리팩토링 작업으로 수정이 간단해짐.)web 관련 Util도 만들어보자 !
 - 하는 이유 경로(path)를 찾을 때, 귀찮은 것들을 빼고 싶어!! (ex. 앞에 반복되는 경로들, .jsp 표시) + 경로 path임!!!!! 이때는 url이 아니다!!!!!!! - UserController.jsp ```java package com.poscodx.mysite.controller; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.poscodx.web.mvc.Action; import com.poscodx.web.mvc.user.UserActionFactory; public class UserController extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String actionName = request.getParameter("a"); Action action = new UserActionFactory().getAction(actionName); action.execute(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ``` - joinformAction에서 ```java package com.poscodx.web.mvc.user; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.poscodx.web.mvc.Action; import com.poscodx.web.mvc.utils.WebUtil; public class JoinFormAction implements Action { @Override public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { request.getRequestDispatcher("/WEB-INF/views/user/joinform.jsp").forward(request, response); WebUtil.forward("user/joinform", request, response); } } ``` - WebUtil.java ```java package com.poscodx.web.mvc.utils; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class WebUtil { public static void forward(String path, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/WEB-INF/views/" + path + ".jsp").forward(request, response); } } ``` - joinSuccess.java도 같이 바꿔줄 수 있다!Login 로그인 실패시,
- LoginAction ```java package com.poscodx.web.mvc.user; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.poscodx.mysite.dao.UserDao; import com.poscodx.mysite.vo.UserVo; import com.poscodx.web.mvc.Action; import com.poscodx.web.utils.WebUtil; public class LoginAction implements Action { @Override public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String email = request.getParameter("email"); String password = request.getParameter("password"); UserVo userVo = new UserDao().findByEmailAndPassword(email, password); //잘못된 비번이 들어오면, userVo = null //로그인 실패 if(userVo == null) { //로그인 실패했을 때, loginform에 던져줄 값. request.setAttribute("email", email); WebUtil.forward("user/loginform", request, response); return; } //로그인 성공 System.out.println(userVo); } } - loginform.jsp ``` name="email" type="text" value="<%=email == null ? "" : email %>"> <% if(email != null) { %>로그인이 실패 했습니다.
<% } %> ```set-cookie
- 로그인 성공을 위한 cookie 학습습 req와 res 사이에, 소통이 끝나면 연결이 끊어진다. 그럼 로그인 후에 로그인 정보는 어떻게 계속 저장하고 있는가? 클라이언트에서 저장한다. 그래서 response일 때, set-cookie를 통해서 클라이언트에서 저장한다. 메모리에 저장하면, 웹 끄고 키면 사라짐. disk에 저장하면 조금 더 오래 남음. 도메인 path랑 같이 보내진걸 기록함. - 쿠키 : 백엔드가 클라이언트에 남기는 것. (Disk) + 키워드 광고 : 검색한 것을 내 disk에 남기고, 구글이 그 쿠키를 보고 관련 광고를 보냄. 내 disk 정보를 구글이, 페이스북이, 등등 다른 곳에서 모두 사용 가능함. > 실습 - 실습 파일 위치 : servlet-practices > servlets -  ```java package servlets; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class CookieServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int visitCount =0; //쿠키 읽기 Cookie[] cookies = request.getCookies(); if(cookies != null && cookies.length>0) { for(Cookie cookie : cookies) { if("visit-count".equals(cookie.getName())) { visitCount =Integer.parseInt( cookie.getValue()); } } } visitCount++; //쿠키 쓰기 (굽기) Cookie cookie = new Cookie("visit-count", String.valueOf(visitCount)); cookie.setPath(request.getContextPath()); cookie.setMaxAge(24 * 60 * 60); // 1day response.addCookie(cookie); // 화면 출력 response.setContentType("text/html; charset=utf-8"); PrintWriter pw = response.getWriter(); pw.print("방문횟수:" + visitCount + "
"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ```  > 쿠키를 잘 보기 위해 확장프로그램 사용하기   - JSession을 로그인에 사용하는 법,  - LoginAction.java ```java //로그인 성공 HttpSession session = request.getSession(true); session.setAttribute("authUser", userVo); // redirect response.sendRedirect(request.getContextPath()); ``` 코드 설명 ```console HttpSession session = request.getSession(true); request 객체로부터 현재의 HTTP 세션을 가져옵니다. 만약 세션이 존재하지 않는다면, true를 전달하여 새로운 세션을 생성합니다. (절대로 null이 되지않음) 세션은 클라이언트와 서버 간의 상태를 유지하는 데 사용됩니다. 예를 들어, 사용자가 로그인한 상태를 유지하거나 장바구니 정보를 저장하는 데 사용될 수 있습니다. session.setAttribute("authUser", userVo); session 객체를 사용하여 세션에 속성(attribute)을 설정합니다. 이 코드에서는 "authUser"라는 이름으로 사용자 정보를 저장하고 있습니다. userVo는 사용자 정보를 담고 있는 객체일 것으로 예상됩니다. 이렇게 세션에 사용자 정보를 저장하면, 해당 사용자의 세션 동안 이 정보를 계속해서 사용할 수 있습니다. 주로 사용자 인증 및 로그인 상태를 관리하는 데에 사용됩니다. 즉, 이 코드는 현재 사용자의 인증된 정보를 세션에 저장하는 것으로, 이후 웹 애플리케이션에서 해당 정보를 사용하여 사용자를 인식하고 관련된 작업을 수행할 수 있도록 합니다. ```로그아웃
- UserActionFactory ```java } else if ("login".equals(actionName)) { action = new LoginAction(); }else if ("logout".equals(actionName)) { action = new LogoutAction(); ``` - LogoutAction ```java package com.poscodx.web.mvc.user; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.poscodx.web.mvc.Action; public class LogoutAction implements Action { @Override public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { HttpSession session = request.getSession(); session.removeAttribute("authUser"); session.invalidate(); response.sendRedirect(request.getContextPath()); } } ``` - header에서 로그인 되면, session값을 토대로 어딜 가든지 기능이 적용되도록함. ```java <%@page import="com.poscodx.mysite.vo.UserVo"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% UserVo authUser = (UserVo)session.getAttribute("authUser"); %>MySite
-
<% if(authUser == null) { %>
- 로그인
- 회원가입
- <% } else { %>
- 회원정보수정
- 로그아웃
- <%=authUser.getName() %>님 안녕하세요 ^^; <% } %> </ul> </div> ``` </details>