-
학원 day79. Redirect, 세션기록 2022. 12. 26. 18:03
- 화면요청은 .jsp 반환
- 조회작업이 아닌 추가, 변경, 삭제 작업과 같은 화면을 요청하지 않는 것들은 redirect:list.hta 처럼 재요청 url이 보내진다.
- 추가(insert)/변경(update)/삭제(delete) 작업 후에는 조회하는 작업을 위해 redirect를 작성한다.
web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" id="WebApp_ID" version="5.0"> <!-- 프론트 컨트롤러 서블릿 배포 --> <servlet> <servlet-name>frontControllerServlet</servlet-name> <servlet-class>com.sample.model2.FrontControllerServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>frontControllerServlet</servlet-name> <url-pattern>*.hta</url-pattern> </servlet-mapping> <!-- 에러페이지 설정 HTTP 응답 코드별로 에러 페이지를 지정할 수 있다. --> <error-page> <error-code>500</error-code> <location>/WEB-INF/views/error/500.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/WEB-INF/views/error/404.jsp</location> </error-page> </web-app>
- .hta로 끝나는 URL 요청이 오면 frontControllerServlet 별칭으로 배포된 com.sample.model2.FrontControllerServlet을 실행한다.
- Redirect 일때는 내부 이동 안하고 브라우저로 바로 재요청 URL(registerSuccess.hta)을 보낸다. 응답이 보내지고나면 기존의 Request객체는 사라지고 다른 화면으로 넘어가면서 새로운 Request, Response 객체가 생성된다.
(반면에, Forward는 내부이동하면서 현재페이지의 Request, Response 객체를 공유한다.)
RegisterController.java public class RegisterController implements Controller { /* * 요청 URI * user/register.hta * 요청 파라미터 * name * id * password * email * 반환값 * redirect:registerSuccess.hta * redirect:registerform.hta?error=fail * 요청처리 내용 * 요청 파라미터 값(회원가입 정보)을 조회한다. * 동일한 아이디가 존재하면 회원가입폼을 요청하는 재요청 URL("redirect:registerform.hta?error=fail")을 응답으로 보낸다. * 동일한 이메일이 존재하면 회원가입폼을 요청하는 재요청 URL("redirect:registerform.hta?error=fail")을 응답으로 보낸다. * 요청 파라미터값을 User객체를 생성해서 저장한다. * UserDao의 void insertUser(User user) 메소드를 호출해서 회원정보를 저장시킨다. * * 로그인 성공 페이지를 요청하는 재요청 URL("redirect:registerSuccess.hta")을 반환한다. */ @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { // 요청 파라미터 값을 조회한다. String name = request.getParameter("name"); String id = request.getParameter("id"); String password = request.getParameter("password"); String email = request.getParameter("email"); // 동일한 아이디가 존재하는지 확인한다. UserDao userDao = UserDao.getInstance(); User savedUser = userDao.getUserById(id); if (savedUser != null) { return "redirect:registerform.hta?error=fail"; } savedUser = userDao.getUserByEmail(email); if (savedUser != null) { return "redirect:registerform.hta?error=fail"; } // User 객체를 생성해서 사용자 정보 저장 User user = new User(); user.setName(name); user.setId(id); user.setPassword(password); user.setEmail(email); // UserDao의 insertUser(User user)를 호출해서 테이블에 저장시킨다. userDao.insertUser(user); return "redirect:registerSuccess.hta?id=" + id; } }
RegisterSuccessController.java /* * 요청 URI * /user/registerSuccess.hta * 요청 파라미터 * id * 반환값 * user/register-success.jsp * 요청처리 내용 * 요청파라미터로 전달받은 아이디로 사용자 정보를 조회해서 요청객체에 속성으로 저장한다. */ public class RegisterSuccessController implements Controller { @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { // 요청 파라미터값을 조회한다. String userId = request.getParameter("id"); // 사용자 아이디로 사용자 정보를 조회한다. UserDao userDao = UserDao.getInstance(); User user = userDao.getUserById(userId); // 조회된 사용자정보를 요청객체에 저장한다. request.setAttribute("username", user.getName()); return "user/register-success.jsp"; } }
register-success.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css"> <title>application</title> </head> <body> <%@ include file="../common/navbar.jsp" %> <div class="container my-3"> <div class="row mb-3"> <div class="col"> <div class="border p-3 bg-light"> <h1 class="mb-4">회원가입 완료</h1> <p class=""><strong>${username }님</strong> 회원가입이 완료되었습니다.</p> <p class=""><strong>${username }님</strong> 로그인 후 다양한 서비스를 사용해 보시기 바랍니다.</p> <div> <a href="loginform.hta" class="btn btn-primary">로그인</a> </div> </div> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
package com.sample.app.controller.user; import com.sample.model2.Controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; /* * 요청 URI * /user/logout.hta * 요청 파라미터 * 없음 * 반환값 * redirect:/app/home.hta // 로그아웃은 어느페이지에서 누를지 모르니까 절대경로로 적은 것임 * 요청처리 내용 * 세션객체를 무효화 시킨다. * 홈화면을 요청하는 재요청 URL("redirect:/app/home.hta")을 반환한다. */ public class LogoutController implements Controller { @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpSession session = request.getSession(false); // 세션 만료시간 지나면 세션객체가 존재하지 않을 것이기 때문에 굳이 존재하지 않는걸 새로만들어서 없앨 필요가 없다. if (session != null) { session.invalidate(); } return "redirect:/app/home.hta"; } }
request.getSession() 과 request.getSession(true)
HttpSession객체를 반환한다.
요청객체에 세션아이디가 없으면 새로운 HttpSession객체를 생성해서 반환한다.
요청객체에 세션아이디가 있지만, 세션아이디와 일치하는 세션객체가 존재하지 않으면 새로운 HttpSession객체를 생성해 서 반환한다.
요청객체에 세션아이디가 있고, 세션아이디와 일치하는 세션객체가 존재하면 그 세션을 반환한다.
request.getSession(false)
요청객체에 세션아이디가 없으면 null을 반환한다.
요청객체에 세션아이디가 있지만, 세션아이디와 일치하는 세션객체가 존재하지 않으면 null을 반환한다.
요청객체에 세션아이디가 있고, 세션아이디와 일치하는 세션객체가 존재하면 그 세션을 반환한다.--> 세션 만료시간이 지나면 세션객체가 존재하지 않을 것이기 때문에 굳이 존재하지 않는걸 새로만들어서 없앨 필요가 없기 때문에 false를 사용한다.
InsertController.java /* * 요청 URI * /post/insert.hta * 반환값 * title * content * 반환값 * redirect:/app/user/loginform.hta?error=deny * redirect:list.hta * 요청처리 내용 * 세션에서 로그인된 사용자 정보를 조회한다. * 사용자정보가 존재하지 않으면 로그인폼을 요청하는 재요청 URL("redirect:/app/user/loginform.hta?error=deny")을 반환한다. * 요청파라미터값을 조회한다. * Post객체를 생성해서 제목, 로그인한 사용자 아이디, 내용을 저장한다. * PostDao의 insertPost(Post post)를 호출해서 게시글정보를 저장시킨다. * 게시글 목록을 요청하는 재요청 URL을 반환한다. */ public class InsertController implements Controller { @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { // 세션에서 로그인된 사용자정보를 조회한다. // 로그인된 사용자정보가 존재하지 않으면 로그인폼을 요청하는 재요청 URL을 반환한다. HttpSession session = request.getSession(); if (session.getAttribute("loginUserId") == null) { return "redirect:/app/user/loginform.hta?error=deny"; } String loginUserId = (String) session.getAttribute("loginUserId"); // 요청파라미터 값을 조회한다. String title = request.getParameter("title"); String content = request.getParameter("content"); // Post객체를 생성해서 게시글 제목, 내용, 로그인한 사용자 아이디를 대입한다. Post post = new Post(); post.setTitle(title); post.setUserId(loginUserId); post.setContent(content); // PostDao객체의 insertPost(Post post)메소드를 호출해서 게시글 정보를 저장한다. PostDao postDao = PostDao.getInstance(); postDao.insertPost(post); // 게시글 목록을 요청하는 재요청 URL을 반환한다. 조회가 아니니까 내부이동 안한다. return "redirect:list.hta"; } }
ListController.java /* * 요청 URI * /post/list.hta * /post/list.hta?page=2 * 요청파라미터 * page * 반환값 * post/list.jsp * 요청처리 내용 * 요청파라미터에서 페이지번호를 조회한다. * 총 데이터갯수를 조회한다. * 페이징처리 처리를 위한 Pagination객체 생성 * 게시글 목록 조회범위를 계산해서 Map객체에 저장한다. * PostDao의 getPosts(Map<String, Object> param) 메소드를 실행해서 게시글을 조회한다. * * 조회된 게시글목록을 요청객체의 속성으로 저장한다. * 생성된 Pagination 객체를 요청객체의 속성으로 저장한다. * * 게시글 목록정보와 페이징정보를 표시하는 jsp 페이지를 반환한다. */ public class ListController implements Controller { @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { // 요청 파라미터값을 조회한다. int currentPage = StringUtils.stringToInt(request.getParameter("page"), 1); PostDao postDao = PostDao.getInstance(); // 총 게시글 갯수를 조회하고, Pagination 객체를 생성한다. int totalRows = postDao.getTotalRows(); Pagination pagination = new Pagination(currentPage, totalRows); // 게시글 목록 조회에 필요한 정보를 저장하는 Map객체를 생성한다. 페이지네이션만 적어줘도 되지만 나중에 검색조건이 늘어날 수 있어서 Map객체를 만들었다. Map<String, Object> param = new HashMap<>(); param.put("begin", pagination.getBegin()); param.put("end", pagination.getEnd()); // PostDao의 getPosts(Map<String, Object> param)메소드를 실행시켜서 게시글 목록을 조회한다. List<PostListDto> postListDtos = postDao.getPosts(param); // 요청객체의 속성으로 게시글 목록정보를 저장한다. request.setAttribute("posts", postListDtos); // 요청객체의 속성으로 페이징처리 정보를 저장한다. request.setAttribute("pagination", pagination); // 내부이동할 jsp 페이지를 반환한다. return "post/list.jsp"; } }
list.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css"> <title>application</title> </head> <body> <%@ include file="../common/navbar.jsp" %> <div class="container my-3"> <div class="row mb-3"> <div class="col"> <h1 class="fs-4 border p-2 bg-light">게시글 목록</h1> </div> </div> <div class="row mb-3"> <div class="col"> <p> 게시글 목록을 확인하세요. <c:if test="${not empty loginUserId }"> <a href="form.hta" class="btn btn-primary btn-sm float-end">새 글쓰기</a> </c:if> </p> <table class="table table-sm"> <colgroup> <col width="7%"> <col width="*"> <col width="10%"> <col width="10%"> <col width="10%"> <col width="15%"> </colgroup> <thead> <tr> <th>번호</th> <th>제목</th> <th class="text-center">작성자</th> <th class="text-center">조회수</th> <th class="text-center">댓글수</th> <th class="text-center">등록일</th> </tr> </thead> <tbody> <c:choose> <c:when test="${empty posts }"> <tr> <td colspan="6" class="text-center">게시글이 없습니다.</td> </tr> </c:when> <c:otherwise> <%-- items="${posts }"는 List<PostListDto>객체가 조회된다. <c:forEach />는 List<PostListDto>객체에 저장된 PostListDto의 갯수만큼 컨텐츠를 반복해서 출력한다. var="dto"는 List<PostListDto>객체에서 순서대로 하나씩 조회한 PostListDto객체가 대입된다. ${dto.no }는 PostListDto객체의 멤버변수 no에 저장된 값을 출력한다. --%> <c:forEach var="dto" items="${posts }"> <%--items에는 List나 배열처럼 반복처리할 수 있는것이 와야한다.--%> <tr> <td>${dto.no }</td> <td><a href="detail.hta?postNo=${dto.no }" class="text-decoration-none">${dto.title }</a></td> <td class="text-center">${dto.userName }</td> <td class="text-center">${dto.readCount }</td> <td class="text-center">${dto.commentCount }</td> <td class="text-center"><fmt:formatDate value="${dto.createdDate }" /></td> </tr> </c:forEach> </c:otherwise> </c:choose> </tbody> </table>
'기록' 카테고리의 다른 글
학원 day81. Todo 게시판 만들기 실습 (0) 2022.12.28 학원 day80. model2 실습 (0) 2022.12.27 학원 day78. JSTL(2) (0) 2022.12.23 학원 day77. JSP의 속성과 스코프, EL, JSTL (0) 2022.12.22 학원 day76. MVC 패턴 (0) 2022.12.21