-
웹개발 - 서블릿 생명주기 Servlet Life Cycle비전공자 공부일기/:: WEB & Front-End 2019. 7. 2. 09:51
2019. 07. 01 필기
서블릿 생명주기란?
서블릿은 클라이언트로부터 요청을 받으면 요청에 의해 WAS(Web Application Server)의 컨테이너가 인스턴스를 생성하여 요청 처리 후 응답한다.
=> WAS의 컨테이너가 서블릿 인스턴스의 생성, 사용(=메소드 호출), 소멸에 대한 전반적인 관리를 담당한다.
=> 만약 기존에 생성된 서블릿 인스턴스가 이미 존재할 경우 새로 인스턴스를 생성하지 않는다
=> WAS가 종료되면 컨테이너가 서블릿 인스턴스를 소멸시킨다
=> 이 때, 서블릿 인스턴스의 생성~사용~소멸 과정을 '생명주기(=Life Cycle)'이라고 한다.서블릿의 생명주기를 확인해보는 예시
@WebServlet(name = "LifeCycleServlet", urlPatterns = { "/life.itwill" }) public class LifeCycleServlet extends HttpServlet { private static final long serialVersionUID = 1L; // 1) 기본 생성자 public LifeCycleServlet() { System.out.println("# LifeCycleServlet 클래스의 기본 생성자"); } // 2) init()으로 초기화 --- 생성자 대신 초기화 작업 @Override public void init(ServletConfig config) throws ServletException { config.getInitParameter("name"); System.out.println("# LifeCycleServlet 클래스의 init() 메소드 호출"); } // 3) service() protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("# LifeCycleServlet 클래스의 service() 메소드 호출"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out=response.getWriter(); out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println("<title>Servlet</title>"); out.println("<body>"); out.println("<h1>서블릿(Servlet)</h1>"); out.println("<hr>"); out.println("<p>Hello, Servlet!!!</p>"); out.println("</body>"); out.println("</html>"); } // 4) destroy() 오버라이드 @Override public void destroy() { System.out.println("# LifeCycleServlet 클래스의 destroy() 메소드 호출"); } }
1) 생성자 : 인스턴스를 생성하는 특별한 메소드
=> 인스턴스 생성시 생성자를 한 번만 호출 : 초기화 작업(필드 초기값 부여)
=> 서블릿은 인스턴스를 딱 한개만 생성한다(싱글톤) 따라서 생성자도 딱 한개만 필요----- 자바 공부 초기부터 초기화에 대한 이해가 무척 어려웠는데, 다음과 같이 이해하기로 했다.
달리기 경주가 열렸다. 선수들도, 관중들도 모두 경주는 출발선에서 시작한다는 건 안다. 하지만 안내원이 제때 출발선이 어디인지 안내하고 세워주지 않으면 우왕좌왕 할 것이다. 초기화는 바로 출발선으로 안내해주는 작업이다. 이렇게 이해했더니 마음이 편해졌다.2) init( ) : 서블릿 인스턴스 생성 후 가장 먼저 자동호출되는 메소드 --- 역시 한 번만 호출됨
=> 생성자 대신 init() 메소드로 초기화 작업을 하는 이유는 ServletConfig 인스턴스를 제공받아 사용하기 때문
--- ServletConfig란? : web.xml 파일에 존재하는 정보를 제공받는 기능이 담긴 인스턴스
--- 이클립스에서 init을 치고 ctrl + space를 누르면 오버라이드 가능한 메소드가 두 가지가 뜨는데, 반드시 ServletConfig 파라미터를 가진 것으로 오버라이드
3) service( ) : 클라이언트의 요청마다 컨테이너에 의해 자동 호출되는 메소드
=> 요청처리 후 응답문서를 생성하여 클라이언트에게 제공하는 메소드
=> doGet() 및 doPost() 메소드도 유사한 작업을 수행하는 메소드
=> 메소드 선언되어 있지 않은 경우 클라이언트에게 405코드 전달
4) destroy( ) : 서블릿 인스턴스가 소멸되기 전에 한 번만 자동 호출되는 메소드
--- 실제로 하는 역할은 없다. 따라서 굳이 오버라이드 하지 않아도 되지만 여기서는 예시를 위해 오버라이드서블릿 인스턴스의 사용을 확인해볼 수 있는 메소드 예시
//클라이언트의 요청마다 서블릿 요청횟수를 클라이언트에게 제공하는 웹 어플리케이션 @WebServlet("/count.itwill") public class CountServlet extends HttpServlet { private static final long serialVersionUID = 1L; /* * //서블릿의 요청 회수를 누적 저장하기 위한 필드 선언 // => WAS 종료시 인스턴스 소멸 - 필드 소멸 >> 계속 남아있게 하려면? * 어딘가에 저장해주어야 한다. // >> 어디에? 파일에 * private int cnt; // 필드는 자동 초기화되기 때문에 =0 으로 초기화해주지 않아도 된다. */ private int newcount; //카운터 파일의 절대경로를 저장하기 위한 필드 private String counterFilePath; //카운터 파일에 저장된 정보를 읽어 필드에 저장 // => 카운터 파일에 없는 경우는 필드에 초기값으로 0 저장 @Override public void init(ServletConfig config) throws ServletException { //카운터 파일의 절대경로를 반환받아 저장 // 컨텍스트의 위치, 서버에 올리는 위치는 각기 다르기 때문에 절대경로는 위험 >> 반드시 컨텍스트에게 자원경로를 달라고 해야함 // >> request한테 없으면 config를 사용하면 절대경로 사용 가능 counterFilePath=config.getServletContext().getRealPath("/WEB-INF/counter.txt"); /* System.out.println("counterFilePath = "+counterFilePath); */ try { //카운터 파일에 대한 입력스트림을 생성하여 저장 ObjectInputStream ois=new ObjectInputStream(new FileInputStream(counterFilePath)); //파일 입력스트림을 이용하여 카운터 정보(서블릿 요청횟수)를 반환받아 필드에 저장 newcount=(Integer)ois.readObject(); //파일 입력스트림 제거 ois.close(); } catch (Exception e) { newcount=0; } } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out=response.getWriter(); //서블릿 요청 횟수를 누적하기 위한 변수 // => 메소드가 종료되면 자동 소멸되는 지역변수 - 변수값 유지 불가능 /* int count=0; */ //서블릿 요청 횟수 누적 newcount++; /* cnt++; */ out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println("<title>Servlet</title>"); out.println("<body>"); out.println("<h1>서블릿 카운트</h1>"); out.println("<hr>"); /* out.println("<p>잘못된 서블릿 요청횟수 = "+count+"</p>"); */ /* out.println("<p>실제 서블릿 요청횟수 = "+cnt+"</p>"); */ out.println("<p>서블릿 요청횟수 = "+newcount+"</p>"); out.println("</body>"); out.println("</html>"); } //필드값(서블릿 요청횟수)을 카운터 파일에 저장할 수 있도록 만듬 // => 카운터 파일이 존재하지 않는 경우 파일 생성하여 필드값 저장 @Override public void destroy() { try { //카운터 파일에 대한 출력스트림을 생성하여 저장 ObjectOutputStream oos= new ObjectOutputStream (new FileOutputStream(counterFilePath)); //파일 출력스트림을 이용하여 카운터 정보(서블릿 요청 횟수)를 반환받아 필드에 저장 oos.writeObject(newcount); //파일 출력스트림 제거 oos.close(); } catch (Exception e) { e.printStackTrace(); } } }
==> 위 예시를 통해, 서블릿 인스턴스가 사용되는 횟수를 확인해볼 수 있다.
'비전공자 공부일기 > :: WEB & Front-End' 카테고리의 다른 글
[WEB : Servlet] Cookie 쿠키(생성, 읽기, 제거) (5) 2019.07.02 Servlet - 파일 업로드 (0) 2019.07.02 웹개발16 - 선택자(selector), 자식요소 (6) 2019.06.26 웹개발13 - 프로토타입 (4) 2019.06.20 웹개발 12 - 객체, 클래스, 메소드 (0) 2019.06.20