Web/Java+Spring

Redirect & Forward

WakaraNai 2021. 5. 10. 16:29
728x90
반응형

Redirect

  • HTTP 프로토콜로 정해진 규칙
  • 서버는 클라이언트의 요청에 대해 특정 URL로 이동. 이를 redirect라고 함.
  • 그 요청의 응답으로 HTTP 상태코드 302로 응답.
    • 이 때 헤더 속 location 값에 이동할 URL을 추가 
  • 클라이언트는 서버로부터 받은 상태값이 302이면 헤더 속 location 값의 URL로 재요청
    • 이 때 브라우저의 주소창은 전송받은 새 URL로 바뀜 
  • servlet이나 JSP는 redirect하기 위해 HttpServletResponse 클래스의 sendRedirect() 를 사용

 

브라우저에서 Redirect 확인하기

개발자도구의 Network 탭

 

예제

웹 브라우저가 redirect01.jsp 요청

redirect01은 redirect02.jsp로 리다이렉팅하는 로직이 실행되도록 함

1번 파일을 열였는데 2번 파일로 URL도 바뀌며 창도 그 내용으로 실행됨

 

redirect01.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
 response.sendRedirect("redirect02.jsp");
%>

 

redirect02.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	redirect된 페이지 입니다
</body>
</html>

 

 

 

 

redirect01.jsp로 Run on Server

 

redirect01.jsp의 URL로 입력해도 redirect02.jsp가 나온다.

이 때 redirect01.jsp을 요청을 받은 서버(WAS)는

302 응답코드와 location 헤더값에 redirect02.jsp를 redirect02.jsp로 보낸다.

redirect01의 요청에 대한 응답은 redirect02로 간다는 점

 

 

 

 

 


 

 

 

Forward

클라이언트의 요청을 다른 servlet을 한 번 거친 후에 응답

 

  1. 웹 브라우저에서 Servlet1에게 요청을 보냄
  2. Servlet1은 요청을 처리한 후, 그 결과를 HttpServletRequest에 저장
  3. Servlet1은 HttpServletRequest와 응답을 위한 HttpServletResponse를, 같은 웹 어플리케이션 안에 있는 Servlet2에게 전송, 넘겨줌.(Forward)
  4. Servlet2는 Servlet1으로부터 받은 HttpServletRequest와 HttpServletResponse를 이용하여 요청을 처리한 후 웹 브라우저에게 결과를 전송

 

 

 

 

Redirect VS Foward

forward는 서버쪽에서 그 요청을 다 처리하지 않고 back에게 일부분 맡기면서 진행됨.

그렇기에 redirect는 url주소가 바뀌지만 forward에서는 클라이언트는 해당 요청을 누가 처리했는지 알 필요가 없기에 URL 주소가 바뀌지 않음. 

 

Redirect - 요청이 서로 다른 두 개

Forward - 요청이 한 개

요청이 들어와서 서버가 내부적으로 옮긴 것뿐 새로운 요청이 아님. 그렇기에 클라이언트가 한 번 요청했을 때 만들었던 요청 객체, 응답 객체가 유지됨. servlet1에서 만든 객체를 다른 servlet이 쓰게 될 때 그 정보를 각각 요청객체, 응답객체에 저장함으로써 넘겨줌.

 

 

Forward 실습

+) service() 메소드만 오버라이딩 하는 이유: 특정 요청인지, 즉 GET인지 POST인지 중요하지 않고 그저 실행되기만 하면 될 때 service()에 적어주기만 하면 되니깐.

 

  • FrontServlet
    • 랜덤한 주사위 값을 구하여 그 값을 NextServlet에게 forward
    • /front로 url-mapping하기. service() 메소드만 오버라이딩
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		// 1~6 정수값 추출.  이 값을 request 객체에 맡겨야 함
		int diceValue = (int)(Math.random()*6)+1;
		// request 객체의 setAttribute()메소드로 값을 객체에 맡김
		// 값과 함께 이 값을 설명하는 단어도 함께 보냄
		request.setAttribute("dice", diceValue);
		
		// forwarding 코드
		// request가 가진 requestDispatcher 객체를 이용
		// 어디로 이동할 지 적어주어야 하는데, 이 때 '/'으로 시작해야함!!
		// NextServlet의 값 주소를 적음
		RequestDispatcher requestDispatcher = request.getRequestDispatcher("/next");
		// 넘겨줄 값들을 적어서 forward
		requestDispatcher.forward(request, response);
	}

 

  • NextServlet
    • FrontServlet으로부터 전달받은 주사위 값만큼 "hello" 출력
    • /next로 url-mapping하기. service() 메소드만 오버라이딩
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>");

	        // 그 값을 가지고 있는 request 객체로부터
	        // 지정한 라벨을 적어서 값을 찾아옴
	        // 값을 꺼내왔을 때 Object 형으로 나오기에
	        // Integer로 형변환
	        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>");
	}

 

 

  • http://localhost:8081/firstweb/front
    • 위의 URl로 FrontServlet이 호출됨

 

 

FrontServlet으로 Run on Server

URL은 /front 그대로이지만 내용은 

NextServlet의 내용이 출력됨. 응답코드 302는 필요없음.

 

 

 


 

 

 

Servlet & JSP 연동

Servlet은 로직을 구현하기에 알맞지만, HTML 출력엔 불편.   (IDE 등에서 지원도 좀 더 잘해줌)

JSP는 로직 구현에 불편하지만 HTML 출력에 편리함.   (결과 출력에 유리)

둘을 함께 다루려면 forward 사용  (Servlet에서 로직 수행하고 그 결과를 JSP에게 forwarding)

 

 

 

 

실습

LogicServlet에서 1~100 사이 랜덤값 2개와, 그 합을 구하여 result.jsp에게 포워딩해서 출력하기

 

  • LogicServlet
    • url-mapping은 /logic, service() 메소드만 오버라이딩
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		int v1 = (int)(Math.random() * 100) + 1;
		int v2 = (int)(Math.random() * 100) + 1;
		int result = v1 + v2;
		
		request.setAttribute("v1", v1);
		request.setAttribute("v2", v2);
		request.setAttribute("result", result);
		
		// webapp 폴더의 바로 아래가 아닌 그 아래 다른 폴더에 접근하려면
		// 경로도 표시해주기
		RequestDispatcher rd = request.getRequestDispatcher("/jsp/result.jsp");
		rd.forward(request, response);
	}

 

 

  • result.jsp
<body>
	<%
		 int v1  = (int)request.getAttribute("v1");
		 int v2  = (int)request.getAttribute("v2");
		 int result  = (int)request.getAttribute("result");
		 
	%>
	<%=v1%> + <%=v2%> = <%=result %>
</body>

 

EL 방식으로 풀이하면 간단해짐.

JSP에서 최대한 자바 코드를 적게 쓰는 것이 좋음

<body>
	${v1} + ${v2} = ${result }
</body>

 

  • 결과

LogicServlet을 Run on Server

 

LogicServlet의 계산 후 result.jsp의 형식에 따라 출력됨

그래서 url은 바뀌지 않음

그리고 JSP 파일은 내부적으로 자바로 바뀜. 

 

 

728x90
반응형

'Web > Java+Spring' 카테고리의 다른 글

EL (Expression Language) for JSP  (0) 2021.05.10
Scope  (0) 2021.05.10
JSP  (0) 2021.05.08
Request, Response  (0) 2021.05.06
Servlet의 Life Cycle  (0) 2021.05.05