WAS의 Servlet 혹은 JSP가 request를 받아 그 request를 처리하다가 추가적인 처리를 같은 Web Application에 포함된 다른 서블릿 or JSP에 위임하는 경우가 있습니다.
현실의 상황을 예로 쉽게 이해해봅시다
고객(클라이언트)이 상담원(서버)에게 어떤 번호 123(URL)으로 상담(Resource)를 요청합니다
상담원은 해당 요청에 모르는 부분은 옆의 직원에게 답을 얻습니다.
상담원이 고객의 상담을 처리해줍니다.
// 1
protected void service(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
// TODO Auto-generated method stub
int diceValue = (int)(Math.random()*6) + 1; // int로 형변환
request.setAttribute("dice", diceValue); //첫번째 인자는 임의의 이름. 두번째 인자는 실제 찾을 값
// Servlet마다 지역변수는 그 안에서 사용되고 소멸되기 때문에 request에 속성을 저장해서 건네주기(forward)할 때
// 이 속성을 사용해서 최종 response한다.
RequestDispatcher rq = request.getRequestDispatcher("/secondServlet");
rq.forward(request, response);
// forward할 경로는 반드시 /로 시작. 그리고 같은 웹어플리케이션 안에서만 이동 가능.
}
// 2
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
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");
int dice = (Integer)request.getAttribute("dice"); // Object타입으로 받은 걸 숫자로 형변환 해야한다.
out.println("dice : " + dice);
for(int i = 0; i < dice; i++) {
out.print("<br>hello");
}
out.println("</body>");
out.println("</html>");
}
각각의 서블릿에서 변수는 각각의 서블릿에서 끝납니다!! 그렇기 때문에 forward(건네주기)를 해서 나머지 처리를 해줘야하는 데 어떻게 할까요?
실행 중인 페이지와 forward에 의해 호출될 페이지는 각각의 지역변수는 당연히 공유할 수 없지만 request, response 객체는 공유할 수 있습니다. (고객의 문의사항은 해결되어 전화가 끊기기 전까지 유요합니다)
request.setAttribute("Object명", Object)
으로 객체를 request에 담을 수 있습니다.
request.getAttribute("Object명")
에서 Object명을 이용해서 객체를 받을 수 있습니다.
request.getRequestDispatcher("/path")
request의 getRequestDispatcher로 건네줄 path를 설정해주고
forward(request, response)
로 request객체와 response객체를 forward할 수 있습니다.
세탁소를 가면 "홍길동"이름으로 코트와 셔츠등등을 맡기는 걸 생각하면 좋을 것 같습니다. 찾을 때도 홍길동만 말하면 여러 형태의 옷이나 신발 등을 한 꺼번에 받을 수 있습니다.
여러가지 형태를 맡겨야 하기 때문에 Object형을 사용하며 반드시 형변환을 해줘야 합니다.
Server가 client 요청에 대해 특정 URL로 이동을 다시 요청하는 rule입니다.
클라이언트가 서버에 Resource 요청을 합니다.
서버는 redirect 상태값인 3xx과 함께 Header에 이동할 Location URL을 추가해서 같이 보냅니다.
클라이언트는 서버에서 받은 값이 302(Found)면 받은 Location으로 Resource를 요청합니다.
서버는 새 Resource에 응답하고 해당 URL로 바뀝니다.
Servlet, JSP redirect하기
sendRedirect()
메소드를 사용합니다.
// 1
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
response.sendRedirect("redirect02.jsp");
%>
// 2
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
redirect된 페이지 입니다.
</body>
</html>
현실의 상황을 예로 쉽게 이해해봅시다
고객(클라이언트)이 상담원(서버)에게 어떤 번호 123(URL)으로 상담(Resource)를 요청합니다
서버는 고객에게 안내를 해줍니다. "고객님 해당 상담내용(Resource)은 다른 부서 124로 다시 문의해주시겠습니까? "
고객은 다시 124로 문의해서 일처리를 합니다.
둘 다 한 페이지에서 다른 URL로 이동할 때 사용하는 HTTP 프로토콜로 정해진 규칙들이란 공통점이 있지만, 큰 차이점이 있습니다.
redirect는 URL이 변경되고, request 객체를 재사용하지 않습니다. (2개의 request요청은 서로 다른 인스턴스!!)
forward는 URL이 변경되지 않습니다. request 객체를 재사용합니다. (하나의 reqeust)
forward는 Web Container의 내부에서 이동하므로 request, response 객체 공유가 가능합니다:)
redirect 방식 : 시스템( session , DB)에 변화가 생기는 요청(로그인, 글작성, 회원가입) 같은 경우에 적합합니다.
forward 방식 : 시스템에 변화가 생기지 않는 단순 조회(검색) 같은 경우에 적합합니다.
글쓰기 같은 경우 글을 작성하고 forward로 건네주기를 했을 경우 사용자가 새로고침을 할 경우에 요청정보가 그대로 살아있어 똑같은 글이 여러 번 작성될 수 있습니다. 하지만, redirect로 하면 다른 URL로 요청을 보내므로 글 작성이 여러 번 수행되지 않습니다