forward란?
WAS의 서블릿이나 JSP가 요청을 받은 후 그 요청을 처리하다가, 추가적인 처리를 같은 웹 어플리케이션안에 포함된 다른 서블릿이나 JSP에게 위임하는 경우가 있다.
이렇게 위임하는 것을 포워드(forward)라고 한다.
forward의 동작 과정은 위 그림과 같다.
- 웹 브라우저에서 Servlet1에게 요청을 보냄
- Servlet1은 요청을 처리한 후, 그 결과를 HttpServletRequest에 저장
- Servlet1은 결과가 저장된 HttpServletRequest와 응답을 위한 HttpServletResponse를 같은 웹 어플리케이션 안에 있는 Servlet2에게 전송(forward)
- Servlet2는 Servlet1으로 부터 받은 HttpServletRequest와 HttpServletResponse를 이용하여 요청을 처리한 후 웹 브라우저에게 결과를 전송
forward vs redirect
얼핏 보면 forward의 기능이 redirect와 비슷해보인다. 하지만 이 둘은 분명한 차이점이 있다.
1. 리다이렉트는 url 주소가 달라지고, 포워드는 url 주소가 달라지지 않는다.
리다이렉트는 클라이언트가 서버에게 요청을 보내면 서버는 어떠한 일을 처리하고 클라이언트에게 새롭게 요청할 곳을 알려준다. 그래서 리다이렉트의 결과는 실제 실행한 뒤에 url 주소가 달라진다.
반면, 포워드는 클라이언트가 요청을 보냈을 때 서버 쪽에서 혼자 처리하는 것이 아니라 또 다른 back에게 일을 넘기는 것이다. 포워드의 경우 클라이언트는 서버에서 서블릿이 혼자 일을 처리했는지, 다른 서블릿에게 일을 위임했는지 알 필요가 없다. 그래서 포워드가 실행되면 url주소는 바뀌지 않는다.
2. 리다이렉트는 request, response 객체가 여러 번 생성되고, 포워드는 한 번만 생성된다.
실제 클라이언트가 서버에게 요청을 하면 반드시 생성되는 객체가 request와 response이다. 요청이 들어와서 응답을 할 때까지 계속 유지가 되어야 한다. 포워드 같은 경우는 이 객체들이 한 번만 만들어진다. 반면, 리다이렉트는 요청과 응답이 여러번 실행되기 때문에 request, response 객체가 여러 번 만들어진다.
forward 실습
2개의 서블릿을 작성해서 forward의 동작을 살펴보았다.
1. FrontServlet, NextServlet이란 두 개의 서블릿을 작성한다.
2. http://localhost:8080/firstweb/front를 요청하게 되면 FrontServlet이 실행되도록 한다.
3. FrontServlet에서는 랜덤한 주사위 값을 구하고, 그 값을 NextServlet에게 forward한다.
4. NextServlet에서는 FrontServlet으로부터 전달 받은 주사위 값만큼 "hello"를 출력한다.
FrontServlet은 포워딩을 수행하는 NextServlet에게 랜덤한 주사위 값을 전달해야한다.
특정한 값을 전달하기 위해서 request의 setAttribute() 메소드를 이용한다.
메소드의 인자로 key와 value를 입력한다.
key에는 NextServlet에서 값을 호출할 이름을 입력한다.(세탁소에서 나중에 찾으러 올 사람 이름을 알려주는 것과 같은 행위)
여기서는 "dice"를 입력했다.
value에는 실제 전달 받을 값을 입력한다. 여기서는 diceValue를 입력했다.
request.setAttribute("dice", diceValue);
또한, FrontServlet은 포워딩을 수행하는 NextServlet에게 request와 response 객체를 전달해야한다.
RequestDispatcher라는 객체를 이용해 전달을 한다.
포워딩을 수행할 서블릿을 지정하기 위해 request의 getRequestDispatcher()메소드를 이용하는데, 인자 값으로 포워딩을 수행할 서블릿의 url을 입력한다.
마지막으로 RequestDispatcher읭 forward() 메소드를 통해 전달할 request와 response를 인자로 받는다.
RequestDispatcher requestDispatehcer = request.getRequestDispatcher("/next");
requestDispatehcer.forward(request, response);
전체 실습 코드는 다음과 같다.
FrontServlet.java
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class FrontServlet
*/
@WebServlet("/front")
public class FrontServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public FrontServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int diceValue = (int)(Math.random() * 6) + 1;
request.setAttribute("dice", diceValue);
RequestDispatcher requestDispatehcer = request.getRequestDispatcher("/next");
requestDispatehcer.forward(request, response);
}
}
NextServlet.java
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ForwardServlet
*/
@WebServlet("/next")
public class NextServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public NextServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>form</title></head>");
out.println("<body>");
int dice = (Integer)request.getAttribute("dice");
out.println("dice : " + dice);
for(int i = 0; i < dice; i++) {
out.print("<br>hello");
}
out.println("</body>");
out.println("</html>");
}
}
실행 결과
[부스트코스 관련 강의 링크]
forward - https://www.edwith.org/boostcourse-web/lecture/16705/
'Tech > BoostCourse - WEB' 카테고리의 다른 글
[부스트코스] Servlet/JSP - Scope (0) | 2020.03.02 |
---|---|
[부스트코스] servlet & jsp 연동 (0) | 2020.02.28 |
[부스트코스] 리다이렉트(redirect)란? (0) | 2020.02.28 |
[부스트코스] JSP 내장객체(Implicit Objects) (0) | 2020.02.25 |
[부스트코스] JSP 문법 (0) | 2020.02.25 |