스프링 부트를 이용하면 내장된 톰캣이 있어서 따로 WAS를 실행하고 WAR를 포함시키는 작업을 하지 않아도 된다. 하지만 스프링 부트가 나오기 전에는 어떻게 사용했고, WAS와 연결되는 구조가 어떻게 될까? 이번에 해당 내용에 대해서 공부하면서 정리해보기로 했다. 이제부터 진행될 과정은 내장 톰캣이 아닌 직접 다운로드 받은 톰캣을 사용하여 진행한다.
ServletContainerInitializer
톰캣과 같은 WAS에서 서블릿을 지원하면 서블릿 컨테이너를 사용할 수 있다. 서블릿을 만들고 어플리케이션 초기화도 수행할 수 있는데 이를 직접 자바 코드로 구현해 볼 수 있다. ServletContainerInitializer를 사용하면 WAS에서 서블릿 컨테이너를 초기화할 때 원하는 코드를 실행하도록 할 수 있다.
public class MyServletContainerInit implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
System.out.println("MyServletContainerInit.onStartup");
}
}
ServletContainerInitializer의 onStartup()을 오버라이딩해서 구현한다. set과 servletContext의 사용은 이후에 알아볼 것이다.

resources 폴더 내에 META-INF 폴더를 만들고 services에 jakarta.servlet.ServletContainerInitializer 파일을 만든다.

여기에 ServletContainerInitializer의 구현체를 작성해준다.
톰캣을 포함하여 실행하면 로그에 MyServletContainerInit.onStartup이 출력되는 것을 확인할 수 있다.
@HandlesTypes
위에서는 단순히 서블릿 컨테이너가 초기화되는 시점에 출력만 해보았고, 이번에는 서블릿을 컨테이너에 등록하는 과정을 진행해보았다.
public interface MyAppInit {
void onStartup(ServletContext servletContext);
}
public class MyAppInitImpl implements MyAppInit {
@Override
public void onStartup(ServletContext servletContext) {
ServletRegistration.Dynamic servlet = servletContext.addServlet("MyTestServlet", MyTestServlet.class);
servlet.addMapping("/my/*");
}
}
MyAppInit의 구현체이다. 서블릿 컨테이너를 매개변수로 받아 서블릿을 추가하고 디스패처 서블릿에서 처리할 경로도 추가한다.
@WebServlet(urlPatterns = "/servlet-test")
public class MyTestServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("MyTestServlet.service");
}
}
테스트용으로 만든 서블릿이다.
@HandlesTypes(MyAppInit.class)
public class MyServletContainerInit implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
System.out.println("MyServletContainerInit.onStartup");
for (Class<?> s : set) {
try {
MyAppInit myAppInit = (MyAppInit) s.getDeclaredConstructor().newInstance();
myAppInit.onStartup(servletContext);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
set은 클래스 정보를 담고있는 집합이다. 여기에 담기는 클래스는 @HandlesTypes로 지정한 인터페이스의 구현체가 자동으로 들어가게 된다. 위에서 보았던 MyAppInit의 구현체인 MyAppInitImpl이 여기에 들어가게 된다.
클래스 정보로 새 인스턴스를 만들고 해당 인스턴스에 서블릿 컨테이너를 전달한다. 즉, 순회하면서 서블릿 컨테이너에 각 서블릿을 등록하는 것이다.
이제 톰캣을 실행하고 http://localhost:8080/my/servlet-test에 접속해보면

다음과 같이 서블릿이 잘 작동되는 것을 알 수 있다.
다음에는 스프링 컨테이너와 서블릿 컨테이너의 초기화에 대해서 알아보겠다.
'공부 > Spring' 카테고리의 다른 글
| [Spring Boot] 자동 라이브러리 관리 알아보기 (0) | 2024.08.26 |
|---|---|
| [Spring] 톰캣 라이브러리로 직접 실행하기 및 jar의 문제점 (0) | 2024.08.05 |
| [Spring] 포인트컷 지시자(Pointcut Designator) (0) | 2024.07.31 |
| [Spring] 자동 프록시 생성기 (0) | 2024.07.29 |
| [Spring] 빈 후처리기 (BeanPostProcessor) (0) | 2024.07.27 |