23년 5월에 작성한 글입니다.
DispatcherServletAutoConfiguration
아래 Configuration 을 포함
DispatcherServletConfiguration
: DispatcherServlet
을 빈으로 등록DispatcherServletRegistrationConfiguration
: DispatcherServletRegistrationBean
을 빈으로 등록DispatcherServler
등록ServletWebServerFactoryConfiguration
아래 빈을 설정한 TomcatServletWebServerFactory
생성
TomcatConnectorCustomizer
: Connector 에 대한 설정 진행TomcatContextCustomizer
: Context 에 대한 설정 진행TomcatProtocolHandlerCustomizer
: Connector 의 ProtocolHandler 에 대한 설정 진행ServletWebServerFactoryAutoConfiguration
아래 빈들을 정의하여 TomcatServletWebServerFactory
에 대한 Auto Configure 진행
ServletWebServerFactoryCustomizer
: 아래 프로퍼티에 대한 설정 진행server.port
server.address
server.server-header
server.shutdown
server.servlet.*
server.ssl.*
server.compression.*
server.http2.*
TomcatServletWebServerFactoryCustomizer
: 아래 프로퍼티에 대한 설정 진행server.tomcat.*
BeanPostProcessorsRegistrar
WebServerFactoryCustomizerBeanPostProcessor
: 초기화 전에 WebServerFactoryCustomizer
을 적용WebServerFactoryCustomizer
: WebServerFactory
에 대해 설정ErrorPageRegistrarBeanPostProcessor
: 초기화 전에 ErrorPageRegistrar
을 적용ErrorPageRegistrar
: 에러 페이지 등록ServletWebServerApplicationContext
#createWebServer
TomcatServletWebServerFactory
에 위임TomcatServletWebServerFactory
TomcatWebServer
서버 생성public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory
implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware {
...
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
for (LifecycleListener listener : this.serverLifecycleListeners) {
tomcat.getServer().addLifecycleListener(listener);
}
// Connector 생성 & 설정
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
// 내부적으로 Server 및 Service 생성 & 설정
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
// 내부적으로 Engine 및 Host 생성 & 설정
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
// 내부적으로 Context 생성
prepareContext(tomcat.getHost(), initializers);
// 내부적으로 톰캣 실행
// DispatcherServletRegistrationBean 이 Context 에 DispatcherServlet 삽입
// Engine -> Host -> Context -> Wrapper(DispatcherServlet)
return getTomcatWebServer(tomcat);
}
}
WebServerStartStopLifecycle#start
시점의 webServer
상태 확인<Server address="localhost" port="-1" shutdown="SHUTDOWN">
<!-- JNDI Global Resource -->
<GlobalNamingResources>
<!-- Empty -->
</GlobalNamingResources>
<Service name="Tomcat">
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="60000"
redirectPort="443" maxThreads="200" socket.directBuffer="false" />
<Engine name="Tomcat" defaultHost="localhost">
<!-- 메모리 기반의 사용자 정보 관리 -->
<Realm className="org.apache.catalina.startup.Tomcat$SimpleRealm" />
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="false" workDir="null">
<Context name="" docBase="{임시로 생성한 디렉토리}" path=""
className="org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedContext">
<Wrapper className="org.apache.catalina.core.StandardWrapper" servletClass="org.springframework.web.servlet.DispatcherServlet">
<!-- 서블릿 매핑 정보를 관리 -->
<Listener className="org.apache.catalina.mapper.MapperListener" />
<Valve className="org.apache.catalina.core.StandardWrapperValve" />
</Wrapper>
<!-- web.xml 을 사용하지 않는 경우 사용 -->
<Listener className="org.apache.catalina.startup.Tomcat$FixContextListener" />
<!-- Jar 파일을 리소스에 추가 -->
<Listener className="org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory$StaticResourceConfigurer" />
<!-- Context 리로드시, 메모리 누수가 발생했는지 확인하기 위한 헬퍼 리스너 -->
<Listener className="org.apache.catalina.core.StandardHost$MemoryLeakTrackingListener" />
<!-- 종료시, 세션 정보 파기 -->
<Listener className="org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory$DisablePersistSessionListener" />
<!-- 'server.tomcat.resource.*' 프로퍼티 적용 -->
<Listener className="org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer$lambda" />
<!-- 서블릿 매핑 정보를 관리 -->
<Listener className="org.apache.catalina.mapper.MapperListener" />
<!-- 사용자 인증을 제외한 보안 검증 수행 -->
<Valve className="org.apache.catalina.authenticator.NonLoginAuthenticator" />
<Valve className="org.apache.catalina.core.StandardContextValve" />
</Context>
<!-- 에러페이지 제공 -->
<Valve className="org.apache.catalina.valves.ErrorReportValve" />
<Valve className="org.apache.catalina.core.StandardHostValve" />
</Host>
<Valve className="org.apache.catalina.core.StandardEngineValve" />
</Engine>
</Service>
</Server>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- JNDI Global Resource -->
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<!-- 동기화 기능 제공 -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- JNDI 기반의 사용자 정보 관리 -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- 액세스 로그 기능 제공 -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>