FrameWorks/Servlet & Jsp

RequestDispatcher

ABCD 2022. 12. 11.
RequestDispatcher란??
RequestDispatcher는 클라이언트로부터 최초에 들어온 요청을 JSP/Servlet 내에서 원하는 자원으로 요청을 넘기는(보내는) 역할을 수행하거나, 특정 자원에 처리를 요청하고 처리 결과를 얻어오는 기능을 수행하는 클래스입니다. 즉 /a.jsp 로 들어온 요청을 /a.jsp 내에서 RequestDispatcher를 사용하여 b.jsp로 요청을 보낼 수 있습니다. 또는 a.jsp에서 b.jsp로 처리를 요청하고 b.jsp에서 처리한 결과 내용을 a.jsp의 결과에 포함시킬 수 있습니다.
요청을 보내는 방법으로는 RequestDispatcher#forward( )와 RequestDispatcher#include( ) 두 가지 방법이 있습니다.
 
RequestDispatcher가 있는 이유. HttpServletResponse#sendRedirect() 와의 차이점
HttpServletResponse를 사용하면 sendRedirect( ) 메서드를 이용하여 지정한 경로로 제어를 이동시킬 수 있습니다. 그러나 sendRedirect( )는 HTTP 리다이렉션을 이용하기 때문에 하나의 요청 범위 안에서 처리를 하는것이 아니라 브라우저에게 Response 후 브라우저측에서 지정받은 요청 경로로 다시 재요청을 하는 방식이기에 두 번의 HTTP 트랜잭션이 발생하며, 서버측에서는 최초에 받은 요청중에 처리한 내용을 리다이렉트 된 요청안에서 공유할 수 없는 문제가 있습니다.  

 

물론 sendRedirect( ) 에서도 쿠키나 세션등을 이용해 특정 상태를 유지하여 공유할 수는 있겠으나, 상황에 따라 제한적일 수 있으며, 코드 레벨 에서의 알고리즘 등을 곧바로 이어가는데에도 한계가 있기 때문에 좋은 방법이라고 할 수는 없을것입니다.
 
그대신 HttpServletResponse를 통해 리다이렉트 하는 방식은 현재 어플리케이션 이외에 다른 자원의 경로를 요청할 수 있는 반면 RequestDispatcher는 현재 처리중인 서블릿이 속해 있는 웹 어플리케이션 범위 내에서만 요청을 제어할 수 있습니다.
 
RequestDispatcher 생성(얻는) 방법
RequestDispatcher는 ServletContext나 ServletRequest 클래스에서 제공하는 팩토리 메서드(Factory Method)를 통해 얻을 수 있습니다. 팩토리 메서드라는 용어에 대해서는 이 글의 범위 밖이므로 디자인 패턴을 참고해 주시기 바랍니다. 
 
ServletContext을 통해서 얻는 법
서블릿 클래스에서 ServletContext를 사용하여 RequestDispatcher를 얻을 수 있습니다.
 
호출 대상을 web.xml에 지정한 서블릿 이름(<servlet-name>)으로 지정하는 방법 
1
2
ServletContext context = this.getServletContext(); 
RequestDispatcher dispatcher = context.getNamedDispatcher("helloServlet");
cs
 
 
호출 대상을 URL 경로로 지정하는 방법. 웹어플리케이션 루트경로를 기준으로 절대경로만 지정할 수 있습니다.
1
2
ServletContext context = this.getServletContext(); 
RequestDispatcher dispatcher = context.getRequestDispatcher("/hello");
cs
 
JSP 페이지에서는 application 기본객체를 이용합니다.
1
2
3
<%
     RequestDispatcher dispatcher = application.getRequestDispatcher("/hello");             
%>
cs
 
ServletRequest를 통해서 얻는 법
서블릿 클래스에서는 service() 메서드나 doGet() doPost() 등에서 ServletRequest의 하위 클래스인 HttpServletRequest를 매개변수로 받기 때문에 이것을 이용하여 RequestDispatcher를 얻을 수 있습니다. HttpServletRequest에서는 URL 경로를 통해서 대상을 지정하는 한가지 방법만을 제공합니다. 그러나 ServletContext를 통해서 대상을 지정할때와는 다르게 절대경로 및 상대경로 모두 지정이 가능합니다. JSP 페이지에서도 ServletRequest의 인스턴스인 request 기본객체가 있으므로 쉽게 얻을 수 있습니다.
1
RequestDispatcher dispatcher = request.getRequestDispatcher("/hello");
cs

 

RequestDispatcher의 forward( ) 메서드
forward() 메서드는 대상 자원으로 제어를 넘기는 역할을 합니다. 브라우저에서 /a.jsp로 요청했을 때 /a.jsp에서 forward()를 실행하여 /b.jsp로 제어를 넘길 수 있습니다. 제어를 넘겨받은 /b.jsp는 처리 결과를 최종적으로 브라우저에게 출력합니다. 브라우저 입장에서는 /a.jsp를 요청했지만 받은 결과는 /b.jsp의 결과입니다. 이때 HTTP 리다이렉트 방식과는 달리 하나의 HTTP 요청(Request) 범위 안에서 동작이 이루어집니다.
 
forward( ) 메서드 실습
forward( )는 특정 자원으로 제어를 넘긴다고 했는데 대상 자원은 Servlet 또는 JSP 페이지가 됩니다(JSP도 결국은 최종적으로 서블릿이므로). 여기서는 서블릿으로 실습을 진행하지만 JSP페이지에서도 application이나 request 내장객체를 통해서 RequestDispatcher 를 얻어 forward( )를 실행할 수 있습니다. 다음과 같이 DispatchTest(/dispatch) -> HelloServlet(/hello) 로 forward( )를 실행하는식으로 진행합니다.
 
DispatchTest 서블릿이고 URL은 /dispatch로 맵핑합니다. RequestDispatcher를 통해 /hello자원으로 forward( )를 실행하는데 /hello는 HelloServlet입니다. 이때 request에 사전처리로 name 속성에 "dololak"을 담았습니다. forward( )는 제어가 넘어간 이후 다지 이전의 자원으로 제어가 돌아가지 않으므로 호출하는쪽의 처리를 모두 완료한 후 제어를 넘겨야 합니다. forward( ) 실행시에는 HttpServletRequest와 HttpServletResponse 객체를 같이 넘겨주기 때문에 호출한 쪽과 호출당한 쪽에서 이 두 가지의 객체를 공유합니다.
1
2
3
4
5
6
7
8
9
10
11
public class DispatchTest extends HttpServlet { 
     @Override 
     protected void service(HttpServletRequest request, HttpServletResponse response) 
                                                    throws ServletException, IOException { 
           request.setCharacterEncoding("UTF-8"); 
           request.setAttribute("name""doloak"); //사전처리 
           
           RequestDispatcher dispatcher = request.getRequestDispatcher("/hello"); 
           dispatcher.forward(request, response); 
     }
}
cs
 

 

 
HelloServlet은 /hello에 맵핑되어있는 서블릿입니다. /dispatch로 호출된 DispatchTest 서블릿에서 forward()를 통해 제어가 넘어옵니다. DispatchTest에서 forward()를 실행하기 전에 담아두었던 name 속성값을 꺼내어 브라우저로 출력합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
public class HelloServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html; charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println("");
        out.println("");
        out.println("");
        out.println("HELLO " + request.getAttribute("name"));
        out.println("");
        out.println("");
    }
}
cs
 
web.xml 서블릿 맵핑정보입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<servlet>
     <servlet-name>dispatchServlet</servlet-name>
     <servlet-class>com.dololak.servlet.DispatchTest</servlet-class>                    
</servlet>
<servlet-mapping>
     <servlet-name>dispatchServlet</servlet-name>
     <url-pattern>/dispatch</url-pattern>
</servlet-mapping>
 
 
<servlet>
     <servlet-name>helloServlet</servlet-name>
     <servlet-class>com.dololak.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
     <servlet-name>helloServlet</servlet-name>
     <url-pattern>/hello</url-pattern>
</servlet-mapping>
cs
 
브라우저로 최종 호출된 내용입니다.  여기서는 사전처리시에 name 속성만을 넘겨주었지만 실무에서는 forward()기능을 다양한 용도로 활용할 수 있습니다.
 
 
forward() 사용시 주의할 점
forward()는 제어를 넘기기 이전에 출력 버퍼를 비우기 때문에 a.jsp -> b.jsp로 호출시 a.jsp에서 어떤 내용을 버퍼에 출력했더라도 무시되며 제어가 넘어간 b.jsp의 출력 내용만 브라우저에게 전달되므로 주의하도록 합니다. 

 

JSP 페이지에서 사용시
JSP 페이지에서 사용시에도 전혀 다를게 없으며, 기본객체들을 이용하면 됩니다.  
1
2
3
4
<%
    RequestDispatcher dispatcher = application.getRequestDispatcher("/hello");            
    dispatcher.forward(request, response);
%>
cs

 

 

출처 : https://dololak.tistory.com/502

728x90
반응형

'FrameWorks > Servlet & Jsp' 카테고리의 다른 글

Web.xml설정으로 Jsp페이지 Include  (0) 2022.12.07

댓글

💲 추천 글