ServletContext 클래스
는 톰캣 컨테이너를 실행하면 각 컨텍스트마다 하나의 ServletContext 객체
를 생성합니다. 여기서 컨텍스트는 하나의 웹 애플리케이션을 의미하며, ServletContext 객체
는 웹 애플리케이션의 공통 자원이나 데이터를 사전에 바인딩해서 서블릿들이 공유하여 사용하도록 만들어줍니다.
톰캣 컨테이너가 종료되게 되면 ServletContext 객체
도 소멸됩니다.
ServletContext 객체
의 기능은 다음과 같습니다.
ServletContext 객체
의 주요 메소드는 다음과 같습니다.
메소드 | 설명 |
---|---|
getAttribute(String name) | name으로 바인딩된 데이터를 가져옴. 없으면 null |
getAttributeNames() | 바인딩된 속성들의 name 반환 |
setAttribute(String name, Object obj) | name으로 obj를 ServletContext에 바인딩 |
removeAttribute(String name) | name으로 바인딩된 데이터 삭제 |
getContext(String uripath) | uripath에 해당되는 객체 반환 |
getInitParameter(String name) | name인 매개변수의 초기화 값 반환 없으면 null |
getInitParameterNames() | 컨텍스트 초기화 관련 매개변수들의 name 반환 |
setInitParameter(String name, String value) | name으로 value를 컨텍스트 초기화 값 설정 |
getMajorVersion() | 서블릿 컨테이너가 지원하는 주요 서블릿 API 버전 반환 |
getRealPath(String path) | path에 해당하는 실제 경로 반환 |
getResource(String path) | path에 해당되는 자원 반환 |
getServerInfo() | 현재 서블릿이 실행되고 있는 컨테이너의 이름과 버전 반환 |
getServletContextName() | ServletContext에 대한 웹 애플리케이션 이름 반환 |
log(String msg) | 로그 파일에 로그 기록 |
먼저 ServletContext 객체
를 이용해서 다른 서블릿으로 데이터를 전달하는 바인딩 방법에 대해 알아보겠습니다.
먼저 바인딩할 데이터를 설정하는 서블릿인 SetServletContexet.java
를 작성합니다.
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@WebServlet("/set")
public class SetServletContext 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 context = getServletContext();
List members = new ArrayList();
members.add("Java Servlet");
members.add("학습 중");
context.setAttribute("members", members); //members라는 이름으로 members List를 바인딩
out.print("<html><body>");
out.print("members에 데이터 바인딩 -> Java Servlet, 학습 중");
out.print("</body></html>");
}
}
다음으로는 바인딩된 데이터를 받아서 화면에 출력하는 GetServletContext.java
를 작성합니다.
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@WebServlet("/get")
public class GetServletContext 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 context = getServletContext();
//members라는 이름을 가진 바인딩 데이터 취득
List members = (ArrayList) context.getAttribute("members");
String skill = members.get(0).toString();
String progress = members.get(1).toString();
out.print("<html><body>");
out.print("기술: " + skill + "<br>");
out.print("학습 상태: " + progress);
out.print("</body></html>");
}
}
작성 후 톰캣 컨테이너를 실행하고 http://localhost:8090/set
으로 접속해서 데이터 바인딩을 먼저 수행해주세요.이후 /get
으로 이동해서 바인딩된 데이터가 제대로 출력됐는지 확인합니다.
당연하겠지만 바인딩된 데이터 없이
/get
부터 호출하면 500 오류가 발생합니다. 바인딩할 members에 데이터가 없는 상태이기 때문입니다.
보통 웹 어플리케이션에서 메뉴와 같은 항목들은 모든 페이지에 걸쳐서 공통적으로 사용됩니다. 당장 velog 상당의 velog로그, 알림/검색, 사용자 프로필(또는 로그인) 메뉴는 블로그 내의 대부분의 페이지에서 공통적으로 나타나는 걸 볼 수 있죠.
이렇게 공통적으로 사용되는 메뉴는 web.xml
에 미리 작성해두고 프로그램 시작 과정에서 불러와서 사용하면 편리합니다. 이 외에도 추가/수정/삭제와 같은 동작도 편리하게 관리할 수 있게 됩니다.
src/main/webapp/WEB-INF/web.xml
에 다음과 같은 내용을 작성합니다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<context-param>
<param-name>menu</param-name>
<param-value>로그인 회원가입 홈으로</param-value>
</context-param>
</web-app>
이제 ContextParameterServlet.java
를 작성합니다.
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/menu")
public class ContextParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
ServletContext context = getServletContext();
//menu는 <param-name>의 이름을 통해 <param-value>의 값을 취득
String menu = context.getInitParameter("menu");
out.println("<html><body>");
out.print(menu);
out.println("</body></html>");
}
}
menu
를 ContextServlet 객체(의 매개변수)를 통해서 접근하기 떄문에 어떻게 접근하던 동일한 메뉴를 띄워주는 것을 볼 수 있습니다.
src/main/webapp/WEB-INF
디렉토리에 /bin
디렉토리를 하나 생성하고 myFile.txt
파일을 하나 생성한 뒤 txt 파일의 내용을 입력해줍니다.
Java, Spring, Servlet, JSP
그리고 작성한 텍스트 파일을 읽기 위한 ContextFileReadServlet.java
를 작성합니다.
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.*;
import java.util.StringTokenizer;
@WebServlet("/readFile")
public class ContextFileReadServlet 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 context = getServletContext();
InputStream inputStream = context.getResourceAsStream("/WEB-INF/bin/myFile.txt");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String str = null;
String elem1 = null;
String elem2 = null;
String elem3 = null;
String elem4 = null;
while ((str = bufferedReader.readLine()) != null) {
//StringTokenizer로 읽은 Line의 문자열을 ,로 분할해서 취득
StringTokenizer stringTokenizer = new StringTokenizer(str, ",");
elem1 = stringTokenizer.nextToken();
elem2 = stringTokenizer.nextToken();
elem3 = stringTokenizer.nextToken();
elem4 = stringTokenizer.nextToken();
}
out.println("<html><body>");
out.println(elem1 + "<br>");
out.println(elem2 + "<br>");
out.println(elem3 + "<br>");
out.println(elem4 + "<br>");
out.println("</body></html>");
bufferedReader.close();
out.close();
}
}
텍스트 파일의 내용을 잘 읽어서 출력해주었음을 확인할 수 있습니다.