0907 | 서블릿 생명주기와 startUp 옵션 / @WebServlet과 @WebListener / servlet context
✅ 간접적으로 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는 다음과 같은 일을 수행한다:
|