DispatcherServlet 的创建过程
【参考文章】:SpringMvc 启动原理源码分析
【参考文章】:【Spring】DispatcherServlet的启动和初始化
【参考文章】:servlet 百度百科
1. servlet 生命周期
一个客户端的请求到达 Server;
Server 创建一个请求对象,处理客户端请求;
Server 创建一个响应对象,响应客户端请求;
Server 加载 Servlet 并调用其 init() 进行初始化;
Server 激活 Servlet 的 service() 方法,传递请求和响应对象作为参数;
service() 方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息;
service() 方法使用响应对象的方法,将响应传回Server,最终到达客户端;
一般 Servlet 只初始化一次(只有一个对象),当 Server 不再需要 Servlet 时(一般当 Server 关闭时),Server 调用 Servlet 的 destroy() 方法。
Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法;
Spring MVC 中由一个单例的 DispatcherServlet 处理所有请求。
2. DispatcherServlet 的创建
2.1 构造方法
先调用父类 FrameworkServlet 的构造方法,再调用自己的构造方法;
public class DispatcherServlet extends FrameworkServlet {
public DispatcherServlet() {
super();
setDispatchOptionsRequest(true);
}
}
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
public FrameworkServlet() {
}
}
2.2 init()
DispatcherServlet 调用基类 HttpServletBean 的 init(),
主要获取 servletContext ,servletConfig 对象
@Override
public final void init() throws ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
} // Set bean properties from init parameters.
try {
// 获取servletConfig
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
// 将dispatcherServlet对象封装到BeanWrapper类里
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
// 获取servletContext
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
// 空的方法
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
throw ex;
} // Let subclasses do whatever initialization they like.
//这个方法由FrameworkServlet提供实现
initServletBean(); if (logger.isDebugEnabled()) {
logger.debug("Servlet '" + getServletName() + "' configured successfully");
}
}
HttpServletBean 的 init() 又会调用 FrameworkServlet 的 initServletBean();
主要初始化 Spring 的 webApplicationContext 对象
@Override
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
if (logger.isInfoEnabled()) {
logger.info("Initializing Servlet '" + getServletName() + "'");
}
long startTime = System.currentTimeMillis(); try {
// 真正有效的方法
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
catch (ServletException | RuntimeException ex) {
logger.error("Context initialization failed", ex);
throw ex;
} if (logger.isDebugEnabled()) {
String value = this.enableLoggingRequestDetails ?
"shown which may lead to unsafe logging of potentially sensitive data" :
"masked to prevent unsafe logging of potentially sensitive data";
logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +
"': request parameters and headers will be " + value);
} if (logger.isInfoEnabled()) {
logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
}
}
初始化 WebApplicationContext后,调用 DispatcherServlet中 的 onRefresh();
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
wac = findWebApplicationContext();
}
if (wac == null) {
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
synchronized (this.onRefreshMonitor) {
// 初始化 Spring MVC 的基本组件
onRefresh(wac);
}
}
if (this.publishContext) {
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
}
return wac;
}
onRefresh() 直接调用 initStrategies() ;
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
initStrategies() 初始化基本组件,启动整个 Spring MVC 框架
protected void initStrategies(ApplicationContext context) {
//初始化上传文件解析器
initMultipartResolver(context);
//初始化本地解析器
initLocaleResolver(context);
//主题处理器
initThemeResolver(context);
//映射处理器
initHandlerMappings(context);
//处理适配器
initHandlerAdapters(context);
//异常处理器
initHandlerExceptionResolvers(context);
//请求到视图名的翻译器
initRequestToViewNameTranslator(context);
//视图解析器
initViewResolvers(context);
//初始化FlashManager
initFlashMapManager(context);
}
DispatcherServlet 的创建过程的更多相关文章
- SpringMVC——DispatcherServlet的IoC容器(Web应用的IoC容器的子容器)创建过程
在上一篇<Spring--Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)>中说到了Web应用中的IoC容器创建过程.这一篇主要讲Sprin ...
- Spring MVC 学习 -- 创建过程
Spring MVC 学习 -- 创建过程 Spring MVC我们使用的时候会在web.xml中配置 <servlet> <servlet-name>SpringMVC< ...
- Spring MVC 原理探秘 - 容器的创建过程
1.简介 在上一篇文章中,我向大家介绍了 Spring MVC 是如何处理 HTTP 请求的.Spring MVC 可对外提供服务时,说明其已经处于了就绪状态.再次之前,Spring MVC 需要进行 ...
- Spring框架系列(13) - SpringMVC实现原理之DispatcherServlet的初始化过程
前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet ...
- ASP.NET Web API 控制器创建过程(二)
ASP.NET Web API 控制器创建过程(二) 前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病 ...
- ASP.NET Web API 控制器创建过程(一)
ASP.NET Web API 控制器创建过程(一) 前言 在前面对管道.路由有了基础的了解过后,本篇将带大家一起学习一下在ASP.NET Web API中控制器的创建过程,这过程分为几个部分下面的内 ...
- Web APi之过滤器创建过程原理解析【一】(十)
前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把[筛子],那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从 ...
- .NET/ASP.NET MVC Controller 控制器(IController控制器的创建过程)
阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...
- 图解JAVA对象的创建过程
前面几篇博文分别介绍了JAVA的Class文件格式.JVM的类加载机制和JVM的内存模型,这里就索性把java对象的创建过程一并说完,这样java对象的整个创建过程就基本上说明白了(当然你要有基础才能 ...
随机推荐
- javaMail实现收发邮件(一)
电子邮件的传输过程 电子邮件系统采用客户/服务器模式.电子邮件传送需要用到以下3个重要模块:MUA(Mail User Agent,邮件用户代理):用户通过它与电子邮件服务器打交道.MUA实际上就是邮 ...
- Linux 下监控用户最大进程数参数(nproc)是否到达上限的步骤:
https://www.cnblogs.com/autopenguin/p/6184886.html 1.查看各系统用户的进程(LWP)数: 注意:默认情况下采用 ps 命令并不能显示出所有的进程.因 ...
- H5相关网址
html5中国 http://www.html5cn.org/ HTML 5 教程 http://www.w3school.com.cn/html5/index.asp http://www. ...
- KALI安装与环境配置
2018-2019 201899224<网络攻防实践>第二周作业 虚拟化网络攻防实验环境包括以下部分: 靶机:包含系统和应用程序安全漏洞,并作为攻击目标的主机.(Windows XP和Li ...
- AltiumDesigner PCB中栅格与格点的切换
PCB中通过快捷键Ctrl+G,进入设置界面. 在弹出的对话框中,在Display,Coarse选择Lines为栅格,Dots为格点,Do Not Draw为无任何显示.
- The Moon and Sixpence摘抄
I had not yet learnt how contradictory is human nature; I did not know how much pose there is in the ...
- @RequestBody配合@JsonFormat注解实现字符串自动转换成Date
2018年08月28日 16:41:15 混合动力火锅 阅读数:440 在controller中使用@RequestBody可以自动将字符串转换成int或者将int转换成字符串,但是Date类型则 ...
- 拉普拉斯平滑处理 Laplace Smoothing
背景:为什么要做平滑处理? 零概率问题,就是在计算实例的概率时,如果某个量x,在观察样本库(训练集)中没有出现过,会导致整个实例的概率结果是0.在文本分类的问题中,当一个词语没有在训练样本中出现,该词 ...
- 【转】Cron表达式详解
Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: (1) Seconds Minutes Hours DayofMonth Mo ...
- (转载)Android开发——Android中常见的4种线程池(保证你能看懂并理解)
0.前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52415337 使用线程池可以给我们带来很多好处,首先通过线程池中线程的重用 ...