[23/07/05] 서블릿 (4)

yeju·2023년 7월 5일
0

Servlet

목록 보기
4/6
post-thumbnail

📌 ServletContext 사용법

ServletContext란?
웹 어플리케이션을 실행할 때 톰캣 컨테이너에서 각 컨텍스트(프로젝트) 마다 하나씩 객체가 생성되는 클래스

여러 명의 사용자가 웹 애플리케이션을 실행하면 각각 사용자에게 하나씩 ServletContext 객체가 생성되고, 톰캣 컨테이너(서버) 종료 시 소멸된다.
ServletContext 객체끼리는 저장 공간을 공유하므로, 공통 자원을 미리 바인딩하고 서블릿에서 해당 자원에 접근할 때 사용한다.

📝 ServletContext 바인딩하기

package sec05.ex01;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

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("/cset")
public class SetServletContext extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		// ServletContext 객체 가져오기
		ServletContext context = getServletContext();
		
		List member = new ArrayList();
		member.add("이순신");
		member.add(30);
		
		// ServletContext에 ArrayList set하기
		context.setAttribute("member",member);
		
		out.print("<html><body>"+member.get(0)+", "+member.get(1)+" 설정</body></html>");
	}
}

getServletContext() 메서드를 호출해 ServletContext 객체의 주소를 가져올 수 있다. request 에 바인딩할 때와 마찬가지로 get/setAttribute() 메서드를 호출해 데이터를 바인딩하고 가져올 수 있다.

package sec05.ex01;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

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("/cget")
public class GetServletContext extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		// ServletContext 객체 가져오기
		ServletContext context = getServletContext();
		
		// ServletContext에 바인딩한 ArrayList 가져오기
		List member = (ArrayList) context.getAttribute("member");
		String name = (String) member.get(0);
		int age = (Integer) member.get(1);
		
		out.print("<html><body>바인딩한 데이터 : "+name+", "+age+"</body></html>");
		// 세션 ID 비교
		HttpSession session = request.getSession();
		out.print("<br>"+session.getId());
	}
}

💻 실행 결과
/cset 에서 바인딩 후 /cget 에 접근했을 때 각각 다른 세션(브라우저) 에서 접근해 동일한 데이터를 가져온 것을 확인할 수 있다.

📝 ServletContext 매개 변수 설정하기

web.xml 파일에 <context-param> 태그로 컨텍스트에서 사용할 초기 파라미터를 설정해 놓으면 ServletContext 객체의 메서드로 해당 파라미터를 사용할 수 있다.

파일명 : web.xml

<web-app>
...
  <!-- 컨텍스트 파라미터 초기 설정 :
  컨테이너 생성 시 ServletContext 객체에 초기 값으로 등록됨 -->
  <context-param>
  	<param-name>menu_member</param-name>
  	<param-value>회원등록 회원조회 회원수정</param-value>
  </context-param>
  <context-param>
  	<param-name>menu_order</param-name>
  	<param-value>주문조회 주문등록 주문수정 주문취소</param-value>
  </context-param>
  <context-param>
  	<param-name>menu_goods</param-name>
  	<param-value>상품조회 상품등록 상품수정 상품삭제</param-value>
  </context-param>
</web-app>
// 메뉴 이름을 미리 설정해놓고 쓰기 실습
...
@WebServlet("/initMenu")
public class ContextParamServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		// ServletContext 객체 가져오기
		ServletContext context = getServletContext();
		// ServletContext 객체에서 파라미터 가져오기
		String menu_member = context.getInitParameter("menu_member");
		String menu_order = context.getInitParameter("menu_order");
		String menu_goods = context.getInitParameter("menu_goods");
		
		out.print("<html><body>");
		out.print("<table border=1 cellspacing=0><tr>메뉴 이름</tr>");
		out.print("<tr><td>"+menu_member+"</td></tr>");
		out.print("<tr><td>"+menu_order+"</td></tr>");
		out.print("<tr><td>"+menu_goods+"</td></tr>");
		out.print("</table></body></html>");
	}
}

📝 ServletContext 파일 입출력하기

ServletContextgetResourceAsStream() 메서드로 파일의 데이터를 읽어와 출력할 수 있다.

// /WEB-INF/bin 폴더 내에 init.txt 파일 만들어 놓기

package sec05.ex03;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

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("/cfile")
public class ContextFileServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		ServletContext context = getServletContext();
		// 파일을 읽어들이기 위해 InputStream 객체 필요
		InputStream is = context.getResourceAsStream("/WEB-INF/bin/init.txt");
		// InputStream 객체가 담은 파일(바이너리 데이터) 내용을 문자로 바꿔 읽기 위해 Reader 객체 필요 (보조 스트림 Buffer 사용)
		BufferedReader buffer = new BufferedReader(new InputStreamReader(is));
		// buffer를 사용해 파일 내용을 읽을 수 있음
		
		String menu = null, menu_member = null, menu_order = null, menu_goods = null;
		
		// buffer에 다음 줄 내용이 있으면 계속 반복
		while((menu = buffer.readLine()) != null) {
			// 파일 내용을 콤마(,)를 구분자로 분리
			StringTokenizer tokens = new StringTokenizer(menu, ",");
			menu_member = tokens.nextToken();
			menu_order = tokens.nextToken();
			menu_goods = tokens.nextToken();
			
			String data = "";
			data += "<html><body>";
			data += menu_member+"<br>"+menu_order+"<br>"+menu_goods+"<br>";
			data += "</body></html>";
			out.print(data);
		}
	}
}
init.txt
메뉴1, 메뉴2, 메뉴3
회원등록 회원조회 회원수정, 주문조회 주문등록 주문수정 주문취소, 상품조회 상품등록 상품수정 상품삭제

[실행 결과]
메뉴1
메뉴2
메뉴3
회원등록 회원조회 회원수정
주문조회 주문등록 주문수정 주문취소
상품조회 상품등록 상품수정 상품삭제

📌 ServletConfig 사용법

ServletConfig란?
톰캣 컨테이너에서 각 서블릿마다 하나씩 객체가 생성되는 클래스

각 서블릿에서만 접근할 수 있으며 공유는 불가능하다. 서블릿과 동일하게 생성되고 서블릿이 소멸 시 같이 소멸된다.
ServletContext 객체를 얻거나 서블릿에 대한 초기화 작업을 할 수 있다.

📝 @WebServlet 애너테이션을 이용한 서블릿 설정

이클립스에서 서블릿을 생성할 때 (프로젝트 우클릭 - New - Servlet
@WebServlet의 구성 요소(url 패턴, 서블릿의 파라미터 등) 설정 가능

설정 후 서블릿을 생성하면 아래 코드처럼 @WebServlet의 내용이 자동으로 설정됨

package sec06.ex01;

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

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

@WebServlet(
		urlPatterns = { 
				"/sInit", 
				"/sInit2"
		}, 
		initParams = { 
				@WebInitParam(name = "email", value = "admin@web.com"), 
				@WebInitParam(name = "tel", value = "010-1111-2222")
		})
public class InitParamServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		// 서블릿에 설정된 초기 파라미터 가져오기
		String email = getInitParameter("email");
		String tel = getInitParameter("tel");
		String data = "";
		data += "<html><body><table>";
		data += "<tr><td>email</td><td>"+email+"</td></tr>";
		data += "<tr><td>tel</td><td>"+tel+"</td></tr>";
		data += "</table></body></html>";
		out.print(data);
	}
}
[실행 결과]
email	admin@web.com
tel		010-1111-2222

📖 9. 쿠키와 세션 알아보기

📌 웹 페이지 연결 기능

HTTP 프로토콜 통신은 stateless 방식으로 통신을 하므로 웹 페이지들끼리 어떤 상태나 정보도 공유하지 않는다. 브라우저에서 새 페이지를 열면 기존의 페이지가 수행한 작업이나 정보를 알 수 없다. 따라서 웹 페이지나 서블릿끼리 상태나 정보를 공유하려면, 세션 트래킹이라는 웹 페이지 연결 기능을 구현해야 한다.

세션 트래킹을 이용하는 방법

  1. <input type="hidden"> 태그 이용 : hidden 속성의 input에 name을 넣어 전송
<!-- 화면에는 보이지 않지만 제출하면 user_hp 데이터가 이동한 페이지에 전송됨 -->
<form>
	<input type="hidden" name="user_hp" value="010-1111-2222">
</form>
  1. URL Rewriting : URL 뒤에 정보를 붙여 다른 페이지로 전송 (GET 방식)
<!-- 페이지 이동 시 URL의 ?뒤에 있는 데이터가 전송됨 -->
<a href="이동할 URL?키=값&키=값&...">이동</a>
  1. 쿠키 : 클라이언트 PC의 Cookie 파일에 정보를 저장한 후 여러 페이지에서 공유
  2. 세션 : 서버 메모리에 정보를 저장한 후 여러 페이지에서 공유

📌 쿠키를 이용한 웹 페이지 연동

쿠키(Cookie)란?
클라이언트 PC마다 정보를 저장해 놓고 필요할 때 여러 웹 페이지에서 사용할 수 있도록 하는 방법

  • 클라이언트 PC에 정보를 저장함
  • 클라이언트에서 사용 유무를 설정할 수 있음

📝 쿠키의 종류

속성Persistence 쿠키Session 쿠키
생성 위치파일로 생성됨브라우저 메모리에 생성됨
종료 시기쿠키 파일 삭제, 쿠키에 설정된 유지 시간이 종료된 경우브라우저를 종료한 경우
용도자동 로그인, 팝업창 보지 않기 설정 등사이트 접속 시에만 인증 정보를 유지해야 할 경우

쿠키의 유지 시간을 양수로 설정하면 클라이언트 PC에 쿠키 파일이 생성되어 Persistence 쿠키로 저장되고, 설정하지 않거나 음수로 설정하면 Session 쿠키로 저장된다.

📝 쿠키 API 사용하기

HttpServletResponseaddCookie() 메서드로 각 클라이언트에 쿠키 정보를 전송한 후 저장
HttpServletRequestgetCookie() 메서드로 쿠키 정보를 서버로 가져옴

(주의) 쿠키에 한글 데이터를 저장하고 꺼내 쓸 때는 인코딩/디코딩 과정이 필요함

package sec02.ex01;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Date;

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("/set")
public class SetCookieValue extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		Date date = new Date();
		// 쿠키에 저장 : cookieTest라는 키(이름)에 한글을 인코딩해서 값으로 저장
		Cookie cookie = new Cookie("cookieTest",URLEncoder.encode("JSP 프로그래밍입니다.","utf-8"));
		// 쿠키 유효 기간 설정 (Persistence 쿠키 : 파일로 저장됨)
		cookie.setMaxAge(24*60*60); // 초 단위, 24h
        // 세션 쿠키 만드는 방법 : 유효 시간을 음수로 지정하기
        // cookie.setMaxAge(-1);
        
		// 생성된 쿠키를 브라우저로 전송
		response.addCookie(cookie);
		
		out.println("현재 시간 : "+date);
		out.println("문자열을 Cookie에 저장합니다.");
	}
}
package sec02.ex01;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;

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("/get")
public class GetCookieValue extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		// 브라우저의 모든 쿠키 정보(쿠키 이름 모음) 배열로 가져오기
		Cookie[] allValues = request.getCookies();
		
		for(int i=0; i < allValues.length; i++) {
			if(allValues[i].getName().equals("cookieTest")) {
				// 쿠키 이름이 cookieTest 인 쿠키 정보 찾기
				// 한글로 된 쿠키 값을 가져올 때는 디코딩 작업이 필요함
				out.println("<h2>Cookie 값 가져오기 : " + URLDecoder.decode(allValues[i].getValue(),"utf-8") + "</h2>");
			}
		}
	}
}

💻 실행 결과
쿠키에 저장한 값을 /get 에서 확인할 수 있다.

크롬 브라우저의 개발자 도구 - 애플리케이션 - 쿠키 에서 현재 사용중인 웹 애플리케이션에 저장된 쿠키 정보를 확인할 수 있다.

📄 [예제] 쿠키 이용해 팝업창 제한하기

자바스크립트를 이용해 쿠키에 접근하여 팝업창을 제어하는 예제

파일명 : popUpTest.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>자바스크립트에서 쿠키 사용</title>
<script type="text/javascript">
	// 페이지가 로드될 때 pageLoad 함수 호출
	window.onload = pageLoad;
	
	function pageLoad() {
		// getCookieValue() 메서드 호출해 반환받은 쿠키 값을 변수에 담기
		notShowPop = getCookieValue();
		if(notShowPop != "true") {
			// notShowPop 값이 true가 아니면 팝업창 띄우기
			window.open("/pro09/popUp.html","pop","width=400, height=500, history=no, resizable=no, status=no, scrollbars=yes, menubar=no");
		}
	}
	function getCookieValue() {
		let result = "false";
		if(document.cookie != "") {
			// 쿠키 정보가 있으면 실행
			// document의 쿠키 정보는 "쿠키이름=값;쿠키이름=값;..." 문자열로 나타남
			// 쿠키 정보를 ; 로 분리해 각각의 쿠키 정보를 배열 형태로 얻기
			cookie = document.cookie.split(";");
			for(let i=0; i<cookie.length; i++) {
				// 각각의 쿠키 정보를 쿠키이름과 값으로 분리
				// element : [쿠키이름, 값]
				element = cookie[i].split("=");
				value = element[0];
				// 정규식을 이용해 쿠키이름 문자열의 공백을 제거
				// ^시작부분 \s 공백을 * 모두 지우기
				value = value.replace(/^\s*/,'');
				if(value=="notShowPop") {
					// 쿠키 이름이 notShowPop인 쿠키 정보의 값을 반환
					result = element[1];
				}
			}
		}
		return result;
	}
	function deleteCookie() {
		// notShowPop 쿠키 값을 false로 만들고 유효 기간 삭제하기 (session 쿠키)
		document.cookie = "notShowPop=" + "false" + ";path=/; expires=-1";
	}
</script>
</head>
<body>
	<form>
		<input type="button" value="쿠키 삭제" onclick="deleteCookie()">
	</form>
</body>
</html>
파일명 : popUp.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript">
	function setPopUpStart(obj) {
		// 체크박스의 체크 여부 확인
		if(obj.checked == true) {
			// 현재 날짜와 시간 가져오기
			let expireDate = new Date();
			let days = 1;
			// 가져온 Date에서 1일 더한 값으로 set
			expireDate.setDate(expireDate.getDate() + days);
			// notShowPop 쿠키 정보 추가하기, 유효 기간은 1일로 설정(persistence 쿠키)
			document.cookie = "notShowPop=" + "true" + ";path=/;expires=" + expireDate.toGMTString();
			window.close();
		}
	}
</script>
</head>
<body>
	알림 팝업창입니다.
	<br><br><br><br><br><br><br><br>
	<form>
		<input type="checkbox" onclick="setPopUpStart(this)"> 오늘 더 이상 팝업 띄우지 않기
	</form>
</body>
</html>

💻 실행 결과
체크박스에 체크를 하면 팝업창이 사라지고 설정 정보가 계속 유지된다.
💻 체크박스에 체크한 후 / 쿠키 삭제 버튼을 누른 후 쿠키 값 비교
체크하면 notShowPop 쿠키 값이 true가 되고 유효 기간이 지정되어 persistence 쿠키가 되고, 쿠키 삭제 버튼을 누르면 쿠키 값이 false가 되고 유효 기간이 사라져 session 쿠키로 등록된다.

profile
🌱

0개의 댓글