webx框架初始化主线之--webxContextLoaderListener

目录
  1. 前言
  2. Tomcat启动与web.xml的解析
    1. Tomcat组件与启动流程
    2. web.xml元素定义与功能
  3. WebxContextoaderListener
    1. Listener中的观察者模式
  4. 总结

上一篇主要介绍了webx框架的项目管理工具maven及AutoConfig插件,这些工具可以让我们的开发更加的灵活。废话不多说,接下来切入webx框架的正题之中。纯属个人理解,欢迎拍砖!

前言

  webx框架的原理,笔者把按照两条主线来进行介绍。也是web开发之中通用的两条主线:初始化主线和请求处理主线。

  • 初始化主线:顾名思义,在web容器开始接受请求之前首先要启动容器并作一定的前期工作,该主线主要简单的从webx框架的启动流程,以及资源加载解析的方面做介绍。
  • 请求处理主线:处理前台发起的request,是web程序的通性。按照如何对request进行control,然后或者处理或者重定向,最终返回结果的设计思路,可以区分不同框架。该主线,主要分析从前台request进入后台容器之后,框架做的一系列处理。

Tomcat启动与web.xml的解析

  绝大多数的web程序都依赖于容器,webx底层基于java servlet而实现,故而必然依赖于Servlet容器。这里的servlet容器使用的是Ali-Tomcat。Ali-Tomcat介绍,戳这里tomcat.alibaba-inc.com

Tomcat组件与启动流程

  先大致了解下Tomcat的几个组件,参见(conf/server.xml);

  • Server组件
    • Server组件代表了整个Catalina(Tomcat内部的servlet容器名称)
  • Service组件
    • Service包括一系列的connector,Executor(可以被连接器共享的线程池),Engine。
1
2
3
4
5
6
<Service>
<Executor name="tomcatThreadPool" namePrefix="catalina-exec- "maxThreads="150" minSpareThreads="4"/>
<!--最常用的连接器,接受来自http的请求-->
<Connector port="80" protocol="HTTP/1.1" connectionTimeout="15000" redirectPort="8443" maxParameterCount="1000" maxThreads="250" maxPostSize="2097152" acceptCount="200" useBodyEncodingForURI="true" />
<Engine></Engine>
</Service>
  • Connector组件
    • 接受来自不同方向的请求,完成与请求方的链接建立:Http请求是web项目中最主要的请求。
  • Engine组件
    • 包含了若干个用来处理请求的接入点。Engine分析请求头然后将请求发送给合适的Host。利用engine的特性,可以通过jvmRoute实现网站的负载均衡。
  • Host组件
    • 虚拟主机,表示了Tomcat角度的主机。每个主机可以有多个不同URL的项目(Context),

全局的Context配置参见conf/context.xml:可以知道web项目的默认入口是web.xml

1
2
3
4
<Context>
<!-- 默认的web项目程序入口 -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>

web.xml元素定义与功能

  既然知道了,web.xml为项目的入口,那么我们看一下在webx框架之中的web.xml。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="GBK" ?>
<web-app>
<!-- 监听器配置 -->
<listener>
<listener-class>
com.alibaba.citrus.webx.context.WebxContextLoaderListener
</listener-class>
</listener>

<!--过滤器声明l-->
<filter>
<filter-name>webx</filter-name>
<filter-class>
com.alibaba.citrus.webx.servlet.WebxFrameworkFilter
</filter-class>
</filter>
<!--过滤器配置,拦截符合正则表达式的url-->
<filter-mapping>
<filter-name>webx</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--错误配置-->
<error-page>
<error-code>400</error-code>
<location>/error.jsp</location>
</error-page>
</web-app>

  web.xml中包含了Servlet,Filter,Listener三类主要的响应处理标签。三者的用途,就不在多说了。在Servlet容器中三者的启动顺序为:Listener > Filter > Servlet。接下来我们来看WebxContextoaderListener

WebxContextoaderListener

  上面说到了web.xml中的Servlet,Filter,Listener启动顺序为Listener > Filter > Servlet。我们可以知道Listener(即WebxContextLoaderListener)首先被初始化。看下图
webcontextloaderListener_

  如上图所示,WebxContextLoaderListener继承自实现了ServletContextListener接口的ContextLoaderListener。当容器启动,触发ServletContextEvent,导致ContextLoaderListener.contextInitialized()方法被调用完成初始化。

  部分类之间的关系如下图所示:
_

  其中导火线是WebxContextoaderListener,除此之外的关键类webxComponentsLoader是对spring自身的上下文加载器ContextLoader的丰富和扩展。此类调用父类接口创建WebApplicationContext,完成最终的初始化。
低调装逼英文看不懂版序列图如下:
_

屌丝不装逼中文秒懂版序列图如下:
_

  首先,服务器开始初始化,将各种Listeners加入观察者队列,WebxContextoaderListener创建webxContextLoader。服务器开始启动时,触发ServletContextEvent事件,导致WebxContextoaderListener调用初始化方法,调用WebxComponentLoader的初始化方法,在webxcomponentloader的初始化方法中,springframework.ContextLoader创建WebApplicationContext(这一步发生了好多事,以后单独一章说说)。最终初始化终于完成了。

  每一个web项目对应一个WebApplicationContext和一个独立的classLoader。二者以ConcurrentHashMap存储。

Listener中的观察者模式

  web.xml中的listener是基于观察者模式的。服务器启动将所有的Listener加入一个观察者队列,当启动事件发生时,触发初始化方法。具体设计模式,自行补充。

总结

  本文描述了监听器监听并创建web应用上下文的的流程,在WebApplicationContext创建过程中,没有做具体的流程描述,在WebApplicationContext创建以及初始化过程之中,使用了由对spring的bean管理进行扩展后的springext丰富了xml的标签定义。如果有机会,会单独写一篇关于这一部分的文章。