上一篇主要介绍了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 | <Service> |
- Connector组件
- 接受来自不同方向的请求,完成与请求方的链接建立:Http请求是web项目中最主要的请求。
- Engine组件
- 包含了若干个用来处理请求的接入点。Engine分析请求头然后将请求发送给合适的Host。利用engine的特性,可以通过jvmRoute实现网站的负载均衡。
- Host组件
- 虚拟主机,表示了Tomcat角度的主机。每个主机可以有多个不同URL的项目(Context),
全局的Context配置参见conf/context.xml:可以知道web项目的默认入口是web.xml1
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)首先被初始化。看下图
如上图所示,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的标签定义。如果有机会,会单独写一篇关于这一部分的文章。