본문 바로가기
웹 프로그래밍/Servlet & JSP

ServletContext로 웹 애플리케이션 단위 정보 공유하기

by kgvovc 2021. 3. 12.
반응형

ServletContext

웹 애플리케이션 단위로 정보를 서버 쪽에 유지할 수 있는 방법은 ServletContext 객체를 사용하는 것입니다. 이번 절에서는 ServletContext의 기본 개념과 주요 메소드에 대해 알아보겠습니다.

 

ServletContext 생성

ServletContext는 서블릿 컨테이너와 통신하기 위해서 사용되는 메소드를 지원하는 인터페이스입니다. 다음 그림과 같이 서블릿 컨테이너가 시작될 때 웹서버에 등록된 웹 애플리케이션 단위로 하나의 ServletContext 객체가 자동으로 생성됩니다. 그리고 웹 애플리케이션 서비스가 중지될 때 소멸합니다. 즉, ServletContext 객체는 웹 애플리케이션과 생명주기(life cycle)가 같습니다. ServletContext 객체를 간단하게 '웹 컨텍스트' 또는 '컨텍스트'라고 합니다.

 

사진 출처: https://tmxhsk99.tistory.com/135

 

WAS에 등록된 웹 애플리케이션 단위로 컨텍스트가 생성되는 이유는 서블릿 컨테이너가 웹 애플리케이션 단위로 모든 자원을 관리할 수 있게 하기 위해서입니다. 즉, 웹 애플리케이션 내에 있는 모든 서블릿 그리고 JSP 간에 정보를 공유할 수 있고, 서블릿 컨테이너에 대한 정보를 추출할 수 있게 하는 기술이 바로 ServletContext입니다.

 

웹 애플리케이션 서비스가 시작될 때 생성된 ServletContext 객체의 추출 방법은 메소드를 이용합니다. 메소드를 이용해 추출되는 ServletContext 객체는 웹 애플리케이션 단위로 사용하기 때문에 동일한 웹 애플리케이션에 존재하는 서블릿들은 동일한 ServletContext 객체를 사용하게 됩니다. ServletContext를 추출하는 메소드는 ServletConfiggetServletContext()입니다.

 

서블릿을 실행할 때 최초의 요청이면 ServletConfig 객체가 생성되며 init() 메소드의 인자값으로 전달됩니다. ServletConfig 객체에서 현재 웹 어플리케이션에 할당된 ServletContext 객체의 주솟값을 추출할 수 있는 getServletContext() 메소드를 제공합니다.

 

 

(1) init() 메소드를 재정의하여 추출하는 방법

다음은 init() 메소드를 재정의하여 ServletConfig 객체를 인자로 받아 ServletContext 객체의 주솟값을 추출하는 예제입니다. ServletContextTest1Servlet이라는 이름의 새로운 서블릿을 작성합니다.

 

package com.edu.test;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;


@WebServlet("/context1")
public class ServletContextTest1Servlet extends HttpServlet{
	
	ServletContext sc;
	@Override
	public void init(ServletConfig config) throws ServletException {
		sc = config.getServletContext();
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		out.print("Context: " + sc);
		out.close();
	}

}

 

 

(2) HttpServlet을 통해 추출하는 방법

ServletContext 객체의 주솟값을 추출할 수 있는 두 번째 방법은 HttpServlet 객체를 이용하는 방법입니다. 서블릿을 구현할 때 반드시 상속해야 하는 HttpServlet 객체의 상위 클래스인 GenericServlet에서 ServletConfig를 상속받아 메소드를 재정의하고 있기 때문에 HttpServlet을 통해서도 getServletContext() 메소드를 사용할 수 있습니다.

 

다음은 HttpServlet을 통해서 ServletContext의 주솟값을 추출하는 예제입니다. ServletContextTest1Servlet 소스를 다음과 같이 수정합니다.

 

~생략~
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	resp.setContentType("text/html;charset=UTF-8");
	PrintWriter out = resp.getWriter();
	ServletContext sc = this.getServletContext();
	out.print("Context : " + sc);
}
~생략

 

 

 

ServletContext 변수

서버가 시작될 때 생성되는 ServletContext 객체는 웹 애플리케이션 단위로 생성되며, 동일한 웹 애플리케이션에 있는 모든 페이지는 동일한 ServletContext를 사용합니다. 그래서 ServletContext 객체가 가지고 있는 변수는 동일한 웹 애플리케이션에 속한 모든 페이지에서 사용할 수 있는 글로벌한 변수입니다. 웹 애플리케이션 단위로 사용할 수 있는 변수를 선언하고 활용하려면 web.xml에 변수를 선언한 다음, 서블릿에서 ServletContext 객체로 추출해서 사용합니다.

 

 

(1) ServletContext 변수 설정

 

ServletContext 객체에 변수를 설정하려면 web.xml 파일에서 <servlet> 태그 위에 다음과 같은 코드를 추가합니다.

~생략~
<display-name>edu</display-name>
<context-param>
	<param-name>contextConfig</param-name>
  	<param-value>/WEB-INF/context.xml</param-value>
</context-param>

<servlet>
~생략~

 

  • <context-param>: ServletContext 객체에 변수를 설정하고자 할 때 사용하는 태그
  • <param-name>: 변수의 이름 설정
  • <param-value>: 변수의 값 설정

 

 

 

(2) ServletContext 변수 추출

 

web.xml에 <context-param>으로 설정한 변수를 추출할 때는 ServletContext 객체에서 제공하는 getInitParameter() 메소드를 활용합니다. getInitParameter() 메소드의 인자로 <param-name> 값을 지정하면 <param-value>에 지정한 값을 String 타입으로 반환합니다. ServletContextTest1Servlet을 다음과 같이 수정합니다.

 

~생략~
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	resp.setContentType("text/html;charset=UTF-8");
	PrintWriter out = resp.getWriter();
	ServletContext sc = this.getServletContext();
	String location = sc.getInitParameter("contextConfig");
	out.print("location : " + location);
	out.close();
}
~생략~

 

 

[참고] 개발 시 <context-param> 태그의 실제 사용 용도

우리가 하나의 서비스를 처리하기 위한 로직을 구현할때 기능별로 파일들을 분리하여 작업합니다. 이때 각 페이지 수준으로 환경설정 파일이 만들어집니다.

 

웹서버가 사용하는 환경설정 파일은 web.xml이지만, 서비스 처리를 위해서는 각 페이지 수준의 환경설정 파일들도 읽어 들이도록 설정해야 하는데요. 환경설정 파일들은 서버의 웹 애플리케이션 서비스 시작과 동시에 읽어 들여야 합니다. 따라서 웹 애플리케이션 서비스 시작과 동시에 생성되는 ServletContext 객체에 환경설정 파일들에 대한 정보를 변수로 전달하고, 실제 환경설정을 하는 페이지에서는 ServletContext 객체를 통해 전달받은 변수를 사용해 환경설정 파일을 찾아가 설정 작업을 진행합니다.

 

예를 들면, 다음과 같습니다.

~생략~
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		/WEB-INF/presentation_layer.xml,
		/WEB-INF/service_layer.xml,
		/WEB-INF/persistent.xml,
	</param-value>
</context-param>
~생략~

 

 

 

서버 정보 추출

웹서버는 웹 애플리케이션 단위로 정보를 나누어 관리하며 서비스합니다. 웹서버에는 웹 애플리케이션당 하나씩 ServletContext 객체가 생성되어 있습니다. 웹 애플리케이션 단위로 만들어진 ServletContext 객체를 통해 웹 애플리케이션에 관한 정보를 추출할 수 있습니다.

 

다음은 ServletContext 객체에서 웹 애플리케이션에 관한 정보를 추출하는 메소드를 활용한 예제입니다. ServletContextTest2Servlet이라는 이름의 새로운 서블릿을 작성합니다.

 

package com.edu.test;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

@WebServlet("/context2")
public class ServletContextTest2Servlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		
		ServletContext sc = this.getServletContext();
		
		out.print("서블릿 버전 : " + sc.getMajorVersion() + "." + sc.getMinorVersion());
		out.print("<br>서버 정보 : " + sc.getServerInfo());
		out.print("<br>웹 애플리케이션 경로 : " + sc.getContextPath());
		out.print("<br>웹 애플리케이션 이름 : " + sc.getServletContextName());
		out.print("<br>파일 실제 경로 : " + sc.getRealPath("/name.html"));
		sc.log("로그 기록!!");
		
		out.close();
		
	}
	
}

 

 

 

 

 

 

웹 애플리케이션 단위 정보 공유

ServletContext 객체는 웹 애플리케이션 단위로 사용되는 객체입니다. 즉, 동일한 웹 애플리케이션 안에 있는 모든 페이지에서 동일한 ServletContext 객체를 사용합니다. 그래서 ServletContext 객체를 이용하여 웹 애플리케이션 단위로 정보를 유지함으로써 공유할 수 있는 것입니다.

 

이처럼 여러 페이지 간에 데이터를 공유하기 위해 사용하는 메소드들은 다음과 같습니다.

 

  • void setAttribute(String name, Object value)

    웹 애플리케이션 범위에서 공유할 데이터를 ServletContext 객체에 등록하는 메소드입니다.

 

  • Object getAttribute(String name)

    ServletContext 객체에 등록한 데이터추출하는 메소드입니다. 인자값으로는 찾으려는 데이터의 등록된 이름을 지정합니다. 동일한 이름으로 등록된 데이터를 찾아서 값을 반환해줍니다. getAttribute() 메소드로 데이터를 추출한 다음에는 항상 원래 데이터 타입으로 캐스팅해서 사용합니다.

 

  • void removeAttribute(String name)

    ServletContext 객체에 setAttribute() 메소드로 등록한 데이터를 삭제합니다. 인자값으로 삭제할 데이터의 등록된 이름을 지정합니다.

 

다음은 ServletContext 객체를 활용하여 데이터를 공유하는 예제입니다. ShareObject라는 이름으로 새 클래스를 생성한 다음, 웹 애플리케이션 범위 내에서 공유할 객체를 생성합니다.

 

// ShareObject.java
package com.edu.test;

public class ShareObject {
	private int count;
	private String str;
	
	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}
	
	public String getStr() {
		return str;
	}
	
	public void setStr(String str) {
		this.str = str;
	}
}

 

다음으로 ServletContext 객체에 데이터를 등록하는 서블릿을 작성합니다.

//ServletContextTest3Servlet.java
package com.edu.test;

import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

@WebServlet("/context3")
public class ServletContextTest3Servlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		
		ServletContext sc = this.getServletContext();
		
		ShareObject obj1 = new ShareObject();
		obj1.setCount(100);
		obj1.setStr("객체 공유 테스트 - 1");
		sc.setAttribute("data1", obj1);
		
		ShareObject obj2 = new ShareObject();
		obj2.setCount(200);
		obj2.setStr("객체 공유 테스트 - 2");
		sc.setAttribute("data2", obj2);
		
		out.print("ServletContext 객체에 데이터 등록을 하였습니다.");
		out.close();
	}
}

 

이어서 ServletContextTest4Servlet이라는 이름으로 ServletContext 객체에 등록된 데이터를 추출하는 서블릿을 작성합니다.

 

//ServletContextTest4Servlet.java

package com.edu.test;

import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

@WebServlet("/context4")
public class ServletContextTest4Servlet extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		
		ServletContext sc = this.getServletContext();
		
		ShareObject obj1 = (ShareObject) sc.getAttribute("data1");
		ShareObject obj2 = (ShareObject) sc.getAttribute("data2");
		
		out.print("DATA 1: " + obj1.getCount() + " , " + obj1.getStr() + "<br>");
		out.print("DATA 2 : " + obj2.getCount() + " , " + obj2.getStr() + "<br>");
		out.close();
		
	}
}
반응형

댓글