😵 ~23.11.10

0907 | 서블릿 생명주기와 startUp 옵션 / @WebServlet과 @WebListener / servlet context

unikue 2023. 9. 7. 14:40

✅ 간접적으로 JSP를 만들어서 쓰는 이유?

👉 웹문서의 출력이 주가되는 서블릿인 경우에는 jasper를 통해 간접적으로 jsp를 만드는게 편리하다.

  • 비효율적인 출력구문반복작업이 줄어든다 out.write()
  • 섞여있는 인코딩, html, 자바코드를 한번에 변환해줌

👉 단순히 값 하나의 출력일때는 문서출력이 아니므로, 서블릿을 직접 만드는게 편리하다.

 

 

#️⃣ 정리되지않은 JSP코드의 문제점

👉 html, java코드가 혼용되어있어서 코드량이 많아질수록 스파게티 코드가 된다 ▶ 자바 코드를 모아놓길 원하게 됨 ▶ 자바의 MVC패턴 도입

 

 


 

✅ WAS 작동시 필요한 개체들

 

🔥 톰캣은 기본적으로 메인함수를 가지고 있음! 내부 코드에 메인함수가 없을때 WAS를 통해서 코드를 돌리는 방법엔 두가지가 있다.

1. 리스너가 시작될 때 WAS를 동작시키기

2. 서블릿에 startup 옵션을 사용하기 (톰캣 시작하자마자 실행됨) ▶ xml이나 annotation으로 설정가능

 

 

✔ Listner - WAS가 실행될 때(==어플리케이션이 실행되는 것) 실행되는 코드. was와 관련된 이벤트가 있을시 작동됨 ApplicationStart, ApplicationEnd

ㄴ Session - 한명의 새로운 사용자가 들어올때 식별하는 것 session start & session end

 

 Servlet - 사용자가 요구하는것과  맥을 일치함 (요청이 있을시 생성됨)

ㄴ start up이란 옵션이 있으면 사용자 요청이 없어도 was가 작동될때 서블릿이 알아서 웹으로 올라간다 (필요에따라 설정)

 

 Filter

 

 

 

 

#️⃣ 서블릿에 startup 옵션을 사용해서 동작시키기

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns="/*", loadOnStartup=1)
public class MybatisConfigServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
	}
}

 

 

 

#️⃣ 서블릿의 생명주기

프레임워크는 틀과 메서드를 오버라이드로 제공한다
👉 프레임워크를 쓸때는 라이프사이클과 왜 쓰는지를 생각하기!!
(오버라이드 했을때 어떤 부분을 수정해서 쓸 수 있는가!를 이해하는것은 라이프사이클을 이해하는 것)
⏩ 서블릿의 생명주기(Servlet Lifecycle)
 웹 애플리케이션 서버(예: Apache Tomcat)에서 서블릿이 생성되고 실행되는 과정을 나타내는 것 
서블릿은 클라이언트 요청에 대한 응답을 생성하는 자바 클래스로, 다음과 같은 생명주기 단계를 거친다:

1. 서블릿 클래스 로딩: 웹 애플리케이션 서버가 시작될 때, 서블릿 컨테이너는 웹 애플리케이션에 등록된 서블릿 클래스를 메모리에 로드한다.

2. 서블릿 인스턴스 생성: 클라이언트가 해당 서블릿에 대한 요청을 최초로 보내면, 서블릿 컨테이너는 해당 서블릿의 인스턴스를 생성한다. 이 단계에서는 init() 메서드가 호출된다. 이 메서드를 사용하여 초기화 작업을 수행할 수 있다.

3. 서비스 메서드 호출: 클라이언트 요청이 있을 때마다 서블릿 컨테이너는 서블릿의 service() 메서드를 호출한다. 이 메서드는 HTTP 요청에 따라 doGet(), doPost(), doPut(), doDelete() 등의 메서드 중 하나를 호출하게 된다. 개발자는 이 메서드를 오버라이딩하여 클라이언트 요청을 처리한다.

4. 요청 처리: service() 메서드 내에서 클라이언트 요청에 대한 처리를 수행한다. 이 단계에서 요청을 분석하고 응답을 생성하여 클라이언트에 반환한다.

5. 서블릿 소멸: 서블릿 컨테이너가 웹 애플리케이션을 종료하거나 서블릿을 더 이상 사용하지 않게 되면, 서블릿의 destroy() 메서드가 호출된다. 이 메서드를 사용하여 리소스 정리 또는 마무리 작업을 수행할 수 있다.

서블릿의 생명주기는 주로 웹 애플리케이션 서버에서 관리된다.
이러한 생명주기를 통해 서블릿은 요청에 대한 응답을 생성하고, 초기화 및 마무리 작업을 수행하여 웹 애플리케이션의 동작을 제어한다.
개발자는 이러한 생명주기 메서드를 오버라이딩하여 서블릿을 커스터마이징할 수 있다.


👉 즉 서블릿을 톰캣에 올릴때 (로딩~소멸까지의 생명주기) 
서블릿을 직접 톰캣실행과 동시에 작동시킬지, 리스너를 사용해서 이벤트를 인식 & 간접적으로 작동시킬지. 에 따라 방법이 달라지는 것.

1. @WebServlet
public class MybatisConfigServlet extends HttpServlet {}

2. @WebListener
public class AppContextListner implements ServletContextListener{}

서블릿이 제공하는 메서드를 중심으로 파악

 

✔ init() : 객체가 만들어지자마자 초기화할것이 있을때 사용.

 service() : 스레드로 만들어서!! 호출 (흐름을 따로 만듦, 여러명이 접속했을때 줄세우기를 하지 않기 위함)

👉 객체는 하나. 서비스는 여러개로 제공하게 된다.

 

 

💥 리스너와 핸들러는 이벤트를 기다리고 있다가 처리한다는 점에서 비슷한 개념으로 인지하면 된다


⏩ [client]-[web listener]-[servlet container]-[servlet]의 관계에서 servlet container가 하는 역할


✔ 클라이언트: 클라이언트는 웹 애플리케이션에 요청을 보내고 응답을 받는 주체.

 웹 리스너: 웹 리스너는 웹 애플리케이션에서 발생하는 이벤트를 감지하고 처리하는 역할.
예를 들어, 웹 애플리케이션의 시작 또는 종료, 세션 생성 또는 소멸과 같은 이벤트를 처리한다. 웹 리스너는 개발자가 구현하고 웹 애플리케이션의 배포 서술자(Deployment Descriptor)에 등록한다.

 서블릿 컨테이너: 서블릿 컨테이너는 서블릿의 생명주기를 관리하고, 클라이언트 요청에 대한 처리를 담당한다. 

-- 서블릿 생명주기 관리: 서블릿 컨테이너는 서블릿 클래스를 로드하고 초기화하며, 클라이언트 요청에 따라 서블릿의 service() 메서드를 호출한다. 또한, 서블릿의 소멸을 관리한다.

-- 요청 라우팅: 클라이언트의 HTTP 요청을 서블릿으로 라우팅하고, 서블릿의 응답을 클라이언트로 전송한다.

-- 스레드 관리: 각 클라이언트 요청은 별도의 스레드로 처리된다. 서블릿 컨테이너는 스레드 풀을 관리하고, 요청을 여러 스레드로 분산 처리한다.

-- 보안 및 인증 관리: 서블릿 컨테이너는 보안 및 인증 관리를 수행한다. 웹 애플리케이션의 보안 설정, 사용자 인증, 권한 부여 등을 처리한다.

-- 세션 관리: 세션 관리를 통해 클라이언트와의 상태를 유지한다. 세션을 생성, 관리하고 클라이언트의 상태 정보를 저장한다.

-- 오류 처리: 서블릿 컨테이너는 예외 처리 및 오류 페이지로의 리다이렉션을 담당한다.

  서블릿: 서블릿은 서버 측에서 동작하는 자바 컴포넌트
클라이언트의 요청을 처리하고 응답을 생성한다. 개발자는 서블릿을 구현하여 특정 기능 또는 서비스를 제공할 수 있다.


서블릿 컨테이너는 이러한 요소들 간의 연결과 조정을 담당하여 웹 애플리케이션의 동작을 원활하게 유지한다. 클라이언트 요청이 들어오면 서블릿 컨테이너는 적절한 서블릿을 호출하고, 웹 리스너로부터 이벤트를 수신하며, 스레드 관리 및 보안 인증과 같은 다양한 역할을 수행한다. 이를 통해 웹 애플리케이션은 안정적으로 동작하고 클라이언트 요청에 응답한다.

 

@WebServlet(urlPatterns="/*", loadOnStartup=1)
public class MybatisConfigServlet extends HttpServlet {

	@Override
	public void init() throws ServletException {
		System.out.println("초기화");
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("서비스");
	}

	@Override
	public void destroy() {
		System.out.println("삭제");
	}
}
@WebListener
public class AppContextListner implements ServletContextListener {
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("서버시작이벤트 발생");
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
	System.out.println("서버종료이벤트 발생");
	}
}

👉 서버작동시 서블릿이 반응할 방향을 HttpServlet / Listener 둘 중 하나로 정해줘야 한다.

 

 

 

✅ ServletContext

#️⃣ context 개념

: 책갈피 같은 개념. 서블릿들이 일을 이어가기 위한 맥락. servlet context는 서블릿 정보를 담아놓을 수 있다.

: tomcat은 Listener에 전역 객체를 담을 수 있는 어플리케이션 전역 저장소로 servletContext를 가지고 있다.

 

👉 jsp는 자신이 전역객체를 가지고 있었지만(JSP 파일이 서블릿으로 변환되면, 서블릿 컨텍스트와 상호 작용할 수 있어서 갖고있음) 지금은 서버가 실행될 때 설정사항들이 초기에 준비될 수 있도록 세팅을 해주는 것.  servlet Context를 통해 전체 서블릿이 공유해야하는 정보를 가질 수 있다

 

@WebListener
public class AppContextListner implements ServletContextListener {
	@Override
	public void contextInitialized(ServletContextEvent event) {
		System.out.println("서버시작이벤트 발생");
		String resource = "mybatis-config.xml";
		InputStream inputStream;

		//jsp에서는 내장객체로 준비가 되어있음 (이름: application)
		//여기선 서버가 시작될 때 전역객체로 준비될 수 있도록 세팅을 해준다
		try {
			inputStream = Resources.getResourceAsStream(resource);
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
			event.getServletContext().setAttribute("sqlSessionFactory", sqlSessionFactory);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("서버종료이벤트 발생");
	}

}

 

ServletContextListener는 웹 애플리케이션의 생명주기 이벤트를 처리하는 인터페이스. JSP 파일이 실행될 때 ServletContextListener는 다음과 같은 일을 수행한다:
  1. 웹 애플리케이션 초기화 이벤트 처리: 웹 애플리케이션(WAR 파일)이 웹 애플리케이션 서버에 배포되고 시작될 때, ServletContextListener는 contextInitialized() 메서드를 호출하여 초기화 작업을 수행한다. 이 시점에서는 웹 애플리케이션 전체의 초기화를 수행할 수 있다. 예를 들어, 데이터베이스 연결 풀을 설정하거나 애플리케이션의 전역 설정을 읽어들이는 작업을 할 수 있다.
  2. 웹 애플리케이션 종료 이벤트 처리: 웹 애플리케이션 서버가 종료되거나 웹 애플리케이션(WAR 파일)이 언바운드(해제)될 때, ServletContextListener는 contextDestroyed() 메서드를 호출하여 마무리 작업을 수행한다. 이 시점에서는 리소스의 정리 작업을 수행할 수 있다. 데이터베이스 연결 풀을 닫거나 애플리케이션에서 사용한 자원을 해제하는 등의 작업을 할 수 있다.
  3. 웹 애플리케이션 범위 데이터 설정: ServletContextListener를 사용하여 웹 애플리케이션 범위에서 공유하는 데이터를 설정할 수 있다. contextInitialized() 메서드 내에서 ServletContext에 속성을 저장하고, 이후에 서블릿, 필터, JSP 등 다양한 웹 컴포넌트에서 이 데이터를 활용할 수 있다.
  4. 환경 설정 로딩: 웹 애플리케이션 시작 시, 설정 파일이나 리소스를 로드하고 이를 웹 애플리케이션의 컴포넌트에서 사용할 수 있도록 준비하는 작업을 수행할 수 있다.
요약하면, ServletContextListener는 웹 애플리케이션의 초기화 및 마무리 작업을 수행하고, 웹 애플리케이션 전역에서 사용할 데이터나 리소스를 설정 및 관리하는 역할을 한다. 이를 통해 웹 애플리케이션의 생명주기 관리와 초기화 작업을 보다 효율적으로 처리할 수 있다.