부스트코스 교육내용(출처)을 바탕으로
학습 자료를 추가하였습니다.
< redirect >
들어가기 전에
게시판 같은 곳에서 글을 작성하는 경우
글 작성 후 글 작성 버튼을 클릭
이때 클라이언트가 서버에게 글을 작성해주세요 라는 요청을 보내게 됩니다.
서버는 해당 글을 저장한 후, 웹 브라우저에게 글 목록으로 이동하라고 응답을 보내게 됩니다.
웹 브라우저는 글 목록으로 이동하라는 서버의 요청을 받은 후, 자동으로 서버에게 글 목록을 요청하여 응답받아 출력하게 됩니다.
서버가 클라이언트에게 어떤 URL로 이동하라는 요청을 보내는 것을 리다이렉트라고 합니다.
핵심 개념
- HttpServletResponse
- sendRedirect()
리다이렉트 (redirect)
- 리다이렉트는 HTTP프로토콜로 정해진 규칙이다.
- 서버는 클라이언트의 요청에 대해 특정 URL로 이동을 요청할 수 있다. 이를 리다이렉트라고 한다.
- 서버는 클라이언트에게 HTTP 상태코드 302로 응답하는데 이때 헤더 내 Location 값에 이동할 URL 을 추가한다. 클라이언트는 리다이렉션 응답을 받게 되면 헤더(Location)에 포함된 URL로 재요청을 보내게 된다. 이때 브라우저의 주소창은 새 URL로 바뀌게 된다..
- 클라이언트는 서버로부터 받은 상태 값이 302이면 Location헤더값으로 재요청을 보내게 된다. 이때 브라우저의 주소창은 전송받은 URL로 바뀌게 된다.
- 서블릿이나 JSP는 리다이렉트하기 위해 HttpServletResponse 클래스의 sendRedirect() 메소드를 사용한다.
브라우저에서 리다이렉트 확인
- 크롬에서 우측버튼을 누르고 검사를 선택한 후 Network탭을 선택한다.
- redirect01.jsp를 실행하면 서버로부터 응답코드로 302를 받는 것을 알 수 있다.
예제 동작 설명
실습코드
- redirect01.jsp, redirect02.jsp 파일을 작성
- 웹 브라우저가 redirect01.jsp을 요청
- redirect01은 redirect02.jsp로 리다이렉팅하는 로직이 실행되도록 함
- 결과 확인
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 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>
생각해보기
- 리다이렉션의 장점과 단점에 대해서 알아봅시다.
< forward >
들어가기 전에
WAS의 서블릿이나 JSP가 요청을 받은 후 그 요청을 처리하다가, 추가적인 처리를 같은 웹 어플리케이션안에 포함된 다른 서블릿이나 JSP에게 위임하는 경우가 있습니다.
이렇게 위임하는 것을 포워드(forward)라고 합니다.
이번 시간엔 이러한 포워드에 대해서 좀 더 자세히 알아보도록 하겠습니다.
학습 목표
- foward를 이해한다.
- foward를 사용 할 수 있다.
핵심 개념
- RequestDispatcher
- forward()
forward란?
- 웹 브라우저에서 Servlet1에게 요청을 보냄
- Servlet1은 요청을 처리한 후, 그 결과를 HttpServletRequest에 저장
- Servlet1은 결과가 저장된 HttpServletRequest와 응답을 위한 HttpServletResponse를 같은 웹 어플리케이션 안에 있는 Servlet2에게 전송(forward)
- Servlet2는 Servlet1으로 부터 받은 HttpServletRequest와 HttpServletResponse를 이용하여 요청을 처리한 후 웹 브라우저에게 결과를 전송
실습코드
FrontServlet.java
package examples;
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);
}
}
NextSevlet.java
package examples;
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("/forward")
public class ForwardServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ForwardServlet() {
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>");
}
}
생각해보기
- 서블릿은 프로그램 로직 개발하기 편리하지만, HTML 태그 출력하기엔 불편.
- JSP는 프로그램 로직 개발하기 불편하지만, HTML 태그 출력하기엔 편리.
- 서블릿과 JSP는 서로 장단점이 반대입니다. 포워드를 이용해서 이러한 단점을 해결하고 싶습니다. 어떻게 해야 할까요?
더 생각해보기
< servlet & jsp연동 >
들어가기 전에
서블릿과 JSP는 서로 상호 보완적인 관계를 가지고 있습니다.
서블릿은 로직을 구현하기에 알맞지만, HTML을 출력하기엔 불편합니다.
JSP는 로직을 구현하는 것은 불편하지만 HTML을 출력하기엔 편리합니다.
이러한 서블릿과 JSP를 좀 더 잘 사용하기 위해서 forward가 사용되는 경우가 많습니다.
이번 시간엔 서블릿과 JSP의 연동에 대해 알아보도록 하겠습니다.
학습 목표
- 서블릿과 JSP를 적절히 이용해서 포워딩을 효율적으로 사용할 수 있다.
핵심 개념
- forward
- request.setAttribute()
- request.getAttribute()
Servlet과 JSP연동
- Servlet은 프로그램 로직이 수행되기에 유리하다. IDE 등에서 지원을 좀 더 잘해준다.
- JSP는 결과를 출력하기에 Servlet보다 유리하다. 필요한 html문을 그냥 입력하면 됨.
- 프로그램 로직 수행은 Servlet에서, 결과 출력은 JSP에서 하는 것이 유리하다.
- Servlet과 JSP의 장단점을 해결하기 위해서 Servlet에서 프로그램 로직이 수행되고, 그 결과를 JSP에게 포워딩하는 방법이 사용되게 되었다. 이를 Servlet과 JSP연동이라고 한다.
servlet jsp연동
실습코드
LogicServlet.java
package examples;
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 LogicServlet
*/
@WebServlet("/LogicServlet")
public class LogicServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LogicServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
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);
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/result.jsp");
requestDispatcher.forward(request, response);
}
}
result.jsp
<%@ 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>
EL표기법으로 출력합니다.<br>
${v1} + ${v2} = ${result} <br><br>
스클립틀릿과 표현식을 이용해 출력합니다.<br>
<%
int v1 = (int)request.getAttribute("v1");
int v2 = (int)request.getAttribute("v2");
int result = (int)request.getAttribute("result");
%>
<%=v1%> + <%=v2 %> = <%=result %>
</body>
</html>
생각해보기
- 객체지향에서 객체는 관련된 것들을 모아서 가지고 있는 특징이 있습니다. 웹 페이지 URL도 관련된 URL이 있습니다. 예를 들어, 게시판 글쓰기, 읽기, 목록 보기 등은 모두 게시판과 관련된 URL일 것입니다. 하지만 지금까지의 예제들을 보면 서블릿은 하나의 URL만 처리하고 있습니다. 하나의 서블릿이 여러 개의 요청을 받을 수는 없을까요?
(힌트 : 서블릿 URL mapping에서 와일드카드('*'기호)를 사용하는 방법에 대해서 조사해보세요.)
'○ WEB > 19.07 BoostCourse_DB연결 웹앱' 카테고리의 다른 글
3-1. application scope (0) | 2019.07.15 |
---|---|
3. scope란? / page scope / request scope / session scope (0) | 2019.07.15 |
1. JSP / 라이프사이클 / 문법 / 내장객체 (0) | 2019.07.13 |
[DB연결 웹앱 JS] 2. window 객체 / DOM / querySelector / Browser Event, Event object, Event handler / ajax / 디버깅 (0) | 2019.07.12 |
[DB연결 웹앱 JS] 1. JS / var, let, const / 연산자 / 문자열 / 함수 선언문, 함수 표현식 / 함수호출과 스택 (0) | 2019.07.12 |