Servlet / JSP #09 상태 유지를 위한 방법

underlier12·2020년 1월 24일
0

SERVLET&JSP

목록 보기
9/16

09. 상태 유지를 위한 방법

개별 입력 방식

이전과 같은 방식보다는 아래와 같은 포맷으로 하나씩 개별적인 값을 전달하여 요청이 들어갈 때가 많음
그럼 이전에 전달된 값들을 저장해 두었다가 서블릿이 결과물을 전달해야 하는 상황이 발생

상태 유지를 위한 5가지 방법

그래서 Application, Session, Cookie 객체를 사용

Application 객체

WAS 상의 서블릿들을 실행된 직후 바로 소멸되기에 그 당시 사용한 값들이나 결과 값들을 넘겨 받거나 하는 행위가 불가. 따라서 '서블릿 Context'라는 저장소를 통해 값들을 저장하고 불러올 수 있음
이 '서블릿 Context'를 'Application 저장소'라고도 부름

서블릿 Context는 서블릿 간 문맥을 연결할 수 있도록 한다는 의미로 해석하면 좋을 듯

코드 작성

calc2.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Calculation</title>
</head>
<body>
	<div>
		<form action="calc2" method="post">
			<div>
				<label>입력 : </label><input name="value" type="text">
			</div>
			<div>
				<input type="submit" name="operator" value="+"/>
				<input type="submit" name="operator" value="-"/>
				<input type="submit" name="operator" value="="/>				
			</div>
		</form>
	</div>
</body>
</html>

Calc2.java

package com.newlecture.web;

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

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

@WebServlet("/calc2")
public class Calc2 extends HttpServlet{
	@Override
	protected void service(HttpServletRequest request
			, HttpServletResponse response) 
					throws ServletException, IOException {
		// Application 저장소 선언
		ServletContext application = request.getServletContext();
		
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=UTF-8");
		
		PrintWriter out = response.getWriter();
		
		String value_ = request.getParameter("value");
		String op = request.getParameter("operator");
		
		int value = 0;
				
		if(!value_.equals("")) value = Integer.parseInt(value_);
		
		// 계산
		if(op.equals("=")) {
			
			int x = (Integer) application.getAttribute("value");
			int y = value;
			String operator = (String) application.getAttribute("op");
			
			int result = 0;
			
			if(operator.equals("+")) {
				result = x + y;					
			} else {
				result = x - y;
			}
			
			response.getWriter().printf("결과 값 : %d\n", result);
			
		} else { // 값 저장
			application.setAttribute("value", value);
			application.setAttribute("op", op);			
		}
	}
}

전달된 operator가 '='이 아니면 Application에 저장 함

Session 객체

Application은 어플리케이션 전역에서 사용가능하지만 세션은 세션 범주에서만 사용 가능
(현재 접속한 사용자를 세션이라 함)

  • 브라우저 종류가 다르면 다른 사용자(세션)으로 인식함
  • 브라우저 종류가 같으면 같은 사용자(세션)으로 인식함

작업관리자를 띄워 보면 동일한 프로세스의 다중 쓰레드로 운영되는 것을 볼 수 있음
--> 즉 서버 측에서는 같은 프로세스가 요청한 것으로 인식이 됨

코드 수정

Application 부분을 Session으로만 변경

package com.newlecture.web;

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

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

@WebServlet("/calc2")
public class Calc2 extends HttpServlet{
	@Override
	protected void service(HttpServletRequest request
			, HttpServletResponse response) 
					throws ServletException, IOException {
		// Application 저장소 선언
		ServletContext application = request.getServletContext();
		
		// Session 선언
		HttpSession session = request.getSession();
		
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=UTF-8");
		
		PrintWriter out = response.getWriter();
		
		String value_ = request.getParameter("value");
		String op = request.getParameter("operator");
		
		int value = 0;
				
		if(!value_.equals("")) value = Integer.parseInt(value_);
		
		// 계산
		if(op.equals("=")) {
			
//			int x = (Integer) application.getAttribute("value");
			int x = (Integer) session.getAttribute("value");
			int y = value;
//			String operator = (String) application.getAttribute("op");
			String operator = (String) session.getAttribute("op");
			
			int result = 0;
			
			if(operator.equals("+")) {
				result = x + y;					
			} else {
				result = x - y;
			}
			
			response.getWriter().printf("결과 값 : %d\n", result);
			
		} else { // 값 저장
//			application.setAttribute("value", value);
			session.setAttribute("value", value);
//			application.setAttribute("op", op);
			session.setAttribute("op", op);
		}
	}
}

동일하게 작동하나 다른 세션일 경우 저장된 값을 불러오지 못함 (세션 별 관리)

사용자(Session) 구분 방식

Session ID가 있어야 Session 공간에 저장 가능 따라서 초기 SID가 없을 경우 SID를 부여함

부여 받은 뒤 다시 서버에 접근하면 이제 Sesion 공간에 접근 가능

식별자는 이렇게 주어짐

세션 유지시간인 타임아웃이 중요함

쿠키로 상태 값 유지

쿠키도 어플리케이션이나 세션처럼 상태값을 지닌다는 점은 같으나 서버 측이 아닌 클라이언트 측에서 값을 저장하고 들고다니는 개념

브라우저에서 자동적으로 설정하는 Header 정보와, 사용자가 직접 입력하는 데이터 등을 보내며 서버에서는 getHeader(), getParameter() 메소드로 받을 수 있음. 서버에서 Cookie를 심을 때 addCookie()를 사용하며 브라우저에 저장하며 해당 정보를 서버에 보내면 서버는 getCookie()로 받음

코드 수정

Calc2.java

package com.newlecture.web;

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

import javax.servlet.ServletContext;
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;
import javax.servlet.http.HttpSession;

@WebServlet("/calc2")
public class Calc2 extends HttpServlet{
	@Override
	protected void service(HttpServletRequest request
			, HttpServletResponse response) 
					throws ServletException, IOException {
		// Application 저장소 선언
		ServletContext application = request.getServletContext();
		
		// Session 선언
		HttpSession session = request.getSession();
		
		// Cookie 선언
		Cookie[] cookies = request.getCookies();
		
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=UTF-8");
		
		PrintWriter out = response.getWriter();
		
		String value_ = request.getParameter("value");
		String op = request.getParameter("operator");
		
		int value = 0;
				
		if(!value_.equals("")) value = Integer.parseInt(value_);
		
		// 계산
		if(op.equals("=")) {
			
//			int x = (Integer) application.getAttribute("value");
//			int x = (Integer) session.getAttribute("value");
			int x = 0;
			
			for(Cookie c : cookies) {
				if(c.getName().equals("value")) {
					x = Integer.parseInt(c.getValue());
					break;
				}
			}
			
			int y = value;
//			String operator = (String) application.getAttribute("op");
//			String operator = (String) session.getAttribute("op");
			String operator = "";
			
			for(Cookie c : cookies) {
				if(c.getName().equals("op")) {
					operator = c.getValue();
					break;
				}
			}
			
			int result = 0;
			
			if(operator.equals("+")) {
				result = x + y;					
			} else {
				result = x - y;
			}
			
			response.getWriter().printf("결과 값 : %d\n", result);
			
		} else { // 값 저장
//			application.setAttribute("value", value);
//			application.setAttribute("op", op);
			
//			session.setAttribute("value", value);
//			session.setAttribute("op", op);
			
			Cookie valueCookie = new Cookie("value", String.valueOf(value));
			Cookie opCookie = new Cookie("op", op);
			response.addCookie(valueCookie);
			response.addCookie(opCookie);
		}
	}
}

쿠키가 여러 개 있을 수 있기에 for문으로 꺼내면서 저장

쿠키는 페이지 마다 다름 따라서 쿠키 내에 URL을 설정 할 수 있음

설정하고 Request 요청 시 심은 Cookie 정보

최종 Request 시 가져갔던 Cookie 정보

쿠키를 확인하는 방법 : 브라우저 설정 > 개인정보 및 보안 > 사이트 설정 > 쿠키 및 사이트 데이터

브라우저가 닫히더라도 쿠키의 수명을 설정해두었다면 해당 기간까지 살아남도록 파일로 저장 됨
설정되지 않으면 메모리에만 존재하며 브라우저 종료 시 같이 소멸

설정 후 쿠키 저장 상황 확인

쿠키를 확인하는 방법 : 브라우저 설정 > 개인정보 및 보안 > 사이트 설정 > 쿠키 및 사이트 데이터

코드 수정

Calc2.java

package com.newlecture.web;

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

import javax.servlet.ServletContext;
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;
import javax.servlet.http.HttpSession;

@WebServlet("/calc2")
public class Calc2 extends HttpServlet{
	@Override
	protected void service(HttpServletRequest request
			, HttpServletResponse response) 
					throws ServletException, IOException {
		// Application 저장소 선언
		ServletContext application = request.getServletContext();
		
		// Session 선언
		HttpSession session = request.getSession();
		
		// Cookie 선언
		Cookie[] cookies = request.getCookies();
		
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=UTF-8");
		
		PrintWriter out = response.getWriter();
		
		String value_ = request.getParameter("value");
		String op = request.getParameter("operator");
		
		int value = 0;
				
		if(!value_.equals("")) value = Integer.parseInt(value_);
		
		// 계산
		if(op.equals("=")) {

			int x = 0;
			
			for(Cookie c : cookies) {
				if(c.getName().equals("value")) {
					x = Integer.parseInt(c.getValue());
					break;
				}
			}
			
			int y = value;

			String operator = "";
			
			for(Cookie c : cookies) {
				if(c.getName().equals("op")) {
					operator = c.getValue();
					break;
				}
			}
			
			int result = 0;
			
			if(operator.equals("+")) {
				result = x + y;					
			} else {
				result = x - y;
			}
			
			response.getWriter().printf("결과 값 : %d\n", result);
			
		} else { // 값 저장	
			Cookie valueCookie = new Cookie("value", String.valueOf(value));
			Cookie opCookie = new Cookie("op", op);
			
			// path 설정
			valueCookie.setPath("/calc2");
			opCookie.setPath("/calc2");
			
			// maxAge 설정 - 24시간 유지
			valueCookie.setMaxAge(24 * 60 * 60);
			opCookie.setMaxAge(24 * 60 * 60);
			
			response.addCookie(valueCookie);
			response.addCookie(opCookie);
		}
	}
}

정리

Application

Session

profile
logos and alogos

0개의 댓글