[Servlet] ServletContext 클래스

Bam·2024년 5월 9일
0

Spring

목록 보기
24/48
post-thumbnail

ServletContext 클래스

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();
    }
}

텍스트 파일의 내용을 잘 읽어서 출력해주었음을 확인할 수 있습니다.

0개의 댓글