Jetty在启动时,先启动Server,调用jettyserver的父类 HandlerWrapper的dostart方法,启动handler,handler是一个HandlerWrapper,总共包含8个Handler,循环调用Handler的start方法,启动各个Handler。
其中XX,负责解析webapp的基本信息,解析web.xml,并将信息保存到实体中。然后调用
WebAppContext
的
doStart
启动, 记载和调用在web.xml中解析并已经加载的所有Listener的
contextInitialized
方法,启动listener。
本文分析的主要包括:webapp的解析和启动、请求的处理、权限的管理、jsp的解析。
(一)webapp的解析和启动包括:
- webapp的解析和启动
- Spring的启动和Bean的加载等
(二)请求的处理包括:
- jetty如何处理请求,并转发到spring
- spring如何处理请求
(三)权限的管理包括:
- jetty如何管理cookies和session
- spring security如何管理权限
(四)jsp的解析
- jsp如何转化为servlet
- 各个模板引擎是如何工作的
一、webapp的解析和启动
服务启动时调用server的dostart方法,dostart方法调用父类HandlerWrapper的dostart方法,dostart方法启动Handler的,这个Handler是一个HandlerCollection,包含三个元素,循环启动三个Handler。
- 0 = {ContextHandlerCollection@3593}
- 1 = {DefaultHandler@3633}
- 2 = {RequestLogHandler@3634}
其中
ContextHandlerCollection是部署的app,webapp目录下面有多少个war,就有多少个
JettyWebAppContext
元素,循环调用
JettyWebAppContext的start方法启动app的部署和解析。
1、web.xml的解析
JettyWebAppContext 的类层次结构如下:
JettyWebAppContext >
WebAppContext > ServletContextHandler > ContextHandler > ScopeHandler > HandlerWrapper > AbstractHandlerContainer > AbstractHandler > AggregateLifeCycle > AbstractLifeCycle
protected void doStart() throws Exception { try { this._metadata.setAllowDuplicateFragmentNames(this.isAllowDuplicateFragmentNames()); this.preConfigure(); super.doStart(); this.postConfigure(); if(this.isLogUrlOnStart()) { this.dumpUrl(); } } catch (Exception var2) { LOG.warn("Failed startup of context " + this, var2); this._unavailableException = var2; this.setAvailable(false); if(this.isThrowUnavailableOnStartupException()) { throw var2; } } }
dostart方法的调用堆栈如下:
at org.eclipse.jetty.webapp.StandardDescriptorProcessor.visitSessionConfig(StandardDescriptorProcessor.java:667) at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-1) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.eclipse.jetty.webapp.IterativeDescriptorProcessor.visit(IterativeDescriptorProcessor.java:85) at org.eclipse.jetty.webapp.IterativeDescriptorProcessor.process(IterativeDescriptorProcessor.java:72) at org.eclipse.jetty.webapp.MetaData.resolve(MetaData.java:366) at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1240) ContextHandler的startContext方法 at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:717) at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:494) at org.mortbay.jetty.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:298)
其中
_configurations 包含如下:
0 = {MavenWebInfConfiguration@3811}
1 = {WebXmlConfiguration@3812}
2 = {MetaInfConfiguration@3813}
3 = {FragmentConfiguration@3814}
4 = {EnvConfiguration@3675}
5 = {PlusConfiguration@3815}
6 = {MavenAnnotationConfiguration@3816}
7 = {JettyWebXmlConfiguration@3817}
MavenWebInfConfiguration主要处理webinf目录和一些临时目录等相关的配置。
WebXmlConfiguration负责定位和解析web.xml配置文件。
MetaInfConfiguration负责解析jar包。
org
.
eclipse
.
jetty
.
webapp
.
WebAppContext
.
startContext最后负责启动所有的Listener,如果使用了Spring框架,此时会启动Spring的ContextLoaderListener。
0 = {ELContextCleaner@5759}
1 = {IntrospectorCleaner@5760}
2 = {LogbackConfigListener@5761}
3 = {SystemLoaderListener@5762}
4 = {OnlineInfoListener@5763}
在WebAppContext的启动过程中启动了SessionHandler。
at org.eclipse.jetty.server.session.HashSessionManager.doStart(HashSessionManager.java:92) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) - locked <0x12c1> (a java.lang.Object) at org.eclipse.jetty.server.session.SessionHandler.doStart(SessionHandler.java:123) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) - locked <0x1287> (a java.lang.Object) at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:95) at org.eclipse.jetty.server.handler.ScopedHandler.doStart(ScopedHandler.java:115) at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:763) at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:249) at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1242) at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:717) at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:494)
2、Spring的启动
第一步解析并把bean的定义加载到集合中,此时不会初始化bean,因为bean可能存在以来关系。
第二步分析bean的依赖关系.
第三步创建并加载bean
bean的解析和加载是一个递归的过程。
如果是XML的context配置,通过web.xml配置文件找到Spring的初始配置文件,并解析。包括外部文件、component-scan、bean的创建、资源的映射等的处理。
其中parseDefaultElement方法根据不同的类型进行不同的处理。