본문 바로가기

TIL/Servlet

[Servlet] forward, redirect, cookie

먼저 html에 폼을 만들어 놓자.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>forward</title>
</head>
<body>
	<h1 align="center">forward</h1>
	
	<form action="forward" method="post">
		<table align="center">
			<tr>
				<td>아이디 : </td>
				<td><input type="text" name="userId"></td>
				<td rowspan="2"><button type="submit" style="height:50px;">로그인</button></td>
			</tr>
			<tr>
				<td>비밀번호 : </td>
				<td><input type="password" name="password"></td>
			</tr>
		</table>
	</form>
</body>
</html>

 

1. 서블릿에서 아이디와 비밀번호 값을 얻는 메소드를 작성한다.

 

위에서 요청 정보를 받았고 모든 비즈니스 로직은 성공이라는 가정 하에 user01을 입력 시

해당 아이디를 user01님 환영합니다 라는 메시지를 출력해주는 화면을 만들자

 

이러한 처리를 해줄 PrintLoginSuccessServlet으로 위임하기 위해서는 RequestDispatcher 인스턴스 생성 후

이 때 다른 서블릿으로 요청하기 위한 데이터는 request에 setAttribute로 전달하여 받는 쪽에서는 getAttribute를 이용해 꺼내서 사용한다.

 

forward받은 서블릿(PrintLoginSuccessServlet)에서도 요청 방식이 get이면 doGet메소드를, 요청 방식이 post이면 doPost메소드를 호출한다. 
request에 이전 서블릿에서 전달하고자 하는 정보를 담았기 때문에 해당 서블릿에서는 다시 꺼내온다.

위 두줄은 최초에 매핑되었던 값, 세 번째 줄은 forward를 통해 attribute에 담긴 값인 아이디가 출력됐다.

 

응답에 필요한 데이터가 다 준비되면 동적인 웹 페이지를 생성한다.

 

변수의 기본 스코프는 메소드(page)이기 때문에 다른 페이지(서블릿)으로 데이터 공유 불가

forward 방식은 request와 response를 넣어서 위임하므로 request에 정보를 저장하여 forward했을 경우 위임 당한 서블릿에서도 서블릿의 정보를 공유할 수 있게 된다.

또한 forward 방식은 해당 서블릿의 존재를 client가 알 필요가 없어 rul 자체가 변경되지 않는다. 


단, 서버로 전송한 데이터가 남아있는 상태로 새로고침(재요청)을 하게되면 요청을 계속 반복하게 되어

DB에 insert하는 행위가 반복되어 중복 행이 발생하는 등의 문제가 있을 수 있다.

이러한 경우는 또 다른 페이지 전환 방식 sendRedirect를 사용해야 한다.

 

서블릿에 네이버 주소를 입력한다.

 

웹에서 링크를 클릭하면 네이버 사이트로 이동한다.

브라우저의 개발자 도구 네트워크 탭을 보면 302번 status code와 함께 naver 사이트로 이동하는 것을 볼 수 있다.

사용자의 url 재작성이라고 불리는 redirect 방식은 302번 응답 코드인 경우 요청에 대한 처리를 잘 했으며 사용자의 url을 강제적으로 redirect 경로로 이동시키라는 의미이다.


redirect를 하는 경우 url이 재작성 되어 새로고침해도 redirect된 페이지에 대한 요청만을 반복한다.

즉, 이전 요청에 남아있던 정보는 더이상 남아있지 않게 된다. 또한 url도 변경된다.

http 요청은 요청 시에 잠시 connection을 맺고 응답 시에도 잠시 connection을 맺으며 요청 단위 당 request 객체는 한 개만 생성이 된다.

따라서 첫 요청 시의 request와 redirect된 페이지의 request는 서로 다른 객체이다.

그렇기 때문에 redirect를 이용하게 되면 이전 서블릿의 값을 공유해서 사용할 수 없게 된다.

그럼 redirect시 값을 유지하는 방법은? 그게 쿠키와 세션이라는 것을 이용할 수 있다.


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1 align="center">Cookie handling</h1>
	<form action="cookie" method="post">
		<table>
			<tr>
				<td>firstName : </td>
				<td><input type="text" name="firstName"></td>
			</tr>
			<tr>
				<td>lastName : </td>
				<td><input type="text" name="lastName"></td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<button type="submit">전송</button>
				</td>
			</tr>
		</table>
	</form>
</body>
</html>

cookie 서블릿에 값 전달 코드 작성

 

 

redirect 서블릿 생성

null값이 나오는 것을 확인할 수 있다.

따라서 request는 공유되지 않는다는 것을 볼 수 있다.

 

redirect는 url을 재작성하여 url을 이용해 요청하는 방식이기 때문에 get방식의 요청이다.

따라서 redirect 되는 서블릿은 doGet 메소드 쪽에서 처리해야 한다.

 

쿠키를 사용하는 방법은 간단하며, 쿠키를 사용하는 절차가 있다.

1. 쿠키를 생성한다.

2. 해당 쿠키의 만료 시간을 설정한다.

3. 응답 헤더에 쿠키를 담는다.

4. 응답한다.

 

하지만 쿠키는 일부 제약 항목이 있다.

쿠키의 이름은 아스키코드 문자만을 사용해야하며 한 번 설정한 쿠키의 이름은 변경할 수 없다.

또한 공백문자와 일부 특수문자 ([ ] ( ) = , " / ? @ " ; )를 사용할 수 없다.

 

cookie 서블릿

 

초 단위 설정으로 하루를 만료시간으로 둘 때의 예시

cookie서블릿
cookie서블릿

 

쿠키를 사용하는 방법

1. request에서 쿠키 목록을 쿠키 배열 형태로 꺼내온다.

2. 쿠키의 getName과 getValue를 이용해 쿠키에 담긴 값을 사용한다.

redirect서블릿

 

쿠키에 있는 값을 뽑아서 화면에 출력한다.

 

cookie 서블릿 전체코드

package com.greedy.section01.cookie;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/cookie")
public class CookieHandlerServlet extends HttpServlet {

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		request.setCharacterEncoding("UTF-8");
		
		String firstName = request.getParameter("firstName");
		String lastName = request.getParameter("lastName");
		
		System.out.println("firstName : " + firstName);
		System.out.println("lastName : " + lastName);
		
		Cookie firstNameCookie = new Cookie("firstName", firstName);
		Cookie lastNameCookie = new Cookie("lastName", lastName);
		
		firstNameCookie.setMaxAge(60 * 60 * 24);
		lastNameCookie.setMaxAge(60 * 60 * 24);
		
		response.addCookie(firstNameCookie);
		response.addCookie(lastNameCookie);
		
		response.sendRedirect("redirect");
	}

}

 

redirect 서블릿 전체코드

package com.greedy.section01.cookie;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String firstName = request.getParameter("firstName");
		String lastName = request.getParameter("lastName");
		
		System.out.println("firstName : " + firstName);
		System.out.println("lastName : " + lastName);
		
		Cookie[] cookies = request.getCookies();
		
		for(int i = 0; i < cookies.length; i++) {
			System.out.println("[cookie] " + cookies[i].getName() + " : " + cookies[i].getValue());
			
			if("firstName".equals(cookies[i].getName())) {
				firstName = cookies[i].getValue();
			} else if("lastName".equals(cookies[i].getName())){
				lastName = cookies[i].getValue();
			}
		}
		
		StringBuilder responseText = new StringBuilder();
		responseText.append("<!doctype html>\n")
					.append("<html>\n")
					.append("<head>\n")
					.append("</head>\n")
					.append("<body>\n")
					.append("<h3>your first name is ")
					.append(firstName)
					.append(" and last name is ")
					.append(lastName)
					.append("</h3>")
					.append("</body>\n")
					.append("</html>\n");
		
		response.setContentType("text/html; charset=UTF-8");
		
		PrintWriter out = response.getWriter();
		out.print(responseText.toString());
		
		out.flush();
		out.close();
	}

}

'TIL > Servlet' 카테고리의 다른 글

[Servlet] mvc-2  (0) 2022.03.21
[Servlet] mvc-1  (0) 2022.03.18
[Servlet] response, exception-handler  (0) 2022.03.07
[Servlet] Parameter(getParameter..)  (0) 2022.03.03
[Servlet] annotation, service method  (0) 2022.03.03