기본적으로 변수의 기본 스코프는 메소드 이기 때문에
다른 페이지(서블릿) 로 데이터를 공유할 수 없다.
하지만 forward 방식은 request 와 response 를 포함하여 위임하므로
request 에 정보를 저장하여 forward 하면 위임받은 서블릿에서도
위임한 서블릿의 정보를 받아올 수 있다.
forward 받은 서블릿의 존재를 클라이언트가 알 필요가 없기 때문에
url 자체는 변경되지 않는다.
forward 방식의 또 다른 특징은 요청 시 서버로 전송한 데이터가
남아있는 상태로 새로고침(재요청)을 하면 동일한 요청을 반복하여
데이터베이스에 insert 하는 등의 행위 등이 중복된 행이 삽입될 가능성이 있다.
따라서 그런 경우는 다른 페이지 전환 방식인 redirect 를 이용한다.
package com.ohgiraffers.section01.forward;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/forward")
public class ReceiveInformationServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userId = req.getParameter("userId");
String password = req.getParameter("password");
System.out.println("userId = " + userId);
System.out.println("password = " + password);
// 다른 서블릿으로 데이터를 request 의 setAttribute 로 전달한다.
req.setAttribute("userId", userId);
// print 라는 경로로 요청을 넘기기 위한 객체 생성
// 이 경로는 서블릿이나 JSP 모두 가능
RequestDispatcher rd = req.getRequestDispatcher("print");
rd.forward(req, resp);
}
}
위의 /forward 서블릿에서 속성을 포워드해서 /print에서 뿌려준다.
package com.ohgiraffers.section01.forward;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/print")
public class PrintLoginSuccessServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userId = (String)req.getAttribute("userId");
System.out.println(userId);
String userId2 = req.getParameter("userId");
System.out.println(userId2);
// 응답에 필요한 데이터가 준비되면 동적인 웹 페이지를 생성한다.
StringBuilder responseText = new StringBuilder();
responseText.append("<!DOCTYPE html>\n")
.append("<html>\n")
.append("<head>\n")
.append("</head>\n")
.append("<body>\n")
.append("<h3 align=\"center\">")
.append(userId)
.append("님 환영합니다. </h3>\n")
.append("</body>\n")
.append("</html>");
resp.setContentType("text/html; charset=UTF-8");
PrintWriter out = resp.getWriter();
out.print(responseText);
out.flush();
out.close();
}
}
redirect 하면 url 이 재작성되어 새로고침할 때 redirect 된 페이지에 대한 요청을 반복한다.
즉, 이전 요청에 포함된 정보는 남아있지 않고, url 이 변경되는 것이 redirect 의 특징이다.
첫 요청 시의 request 와 현재 redirect 된 페이지의 request 는 서로 다른 객체이므로
redirect 를 쓰면 이전 서블릿의 값을 공유해서 사용할 수 없다.
http 요청은 요청 시 잠시 connection 을 맺고 응답 시에도 잠시 connection 을 맺으며
요청 단위 당 request 객체는 한 개만 생성된다.
package com.ohgiraffers.section01.othersite;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/othersite")
public class OtherSiteRedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get 요청 후 naver 로 redirect");
resp.sendRedirect("https://www.naver.com");
}
}
package com.ohgiraffers.section02.otherservlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/otherservlet")
public class OtherServletRedirectTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get 요청 정상 수락");
System.out.println(resp); // org.apache.catalina.connector.ResponseFacade@5c5717be
resp.sendRedirect("redirect");
}
}
package com.ohgiraffers.section02.otherservlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("이 서블릿으로 redirect 성공");
System.out.println(resp); // org.apache.catalina.connector.ResponseFacade@70daeadb
resp.setContentType("text/html; charset=utf-8");
PrintWriter out = resp.getWriter();
out.print("<h1>이 서블릿으로 redirect 성공</h1>");
out.flush();
out.close();
}
}