spring mvc DispatcherServlet解读
spring mvc DispatcherServlet解读
DispatcherServlet的继承和实现
IDEA按快捷键:ctrl+alt+u,就可以查看DispatcherServlet的继承的类和实现的接口。
从继承图可以得知:
- DispatcherServlet本质是一个HttpServlet
- HttpServletBean,FrameworkServlet,DispatcherServlet是属于SpringMVC的类
DispatcherServlet初始化
DispatcherServlet
DispatcherServlet看initStrategies(),该方法用于初始化各类解析器。
onRefresh(ApplicationContext context),该方法用于刷新策略
/*** This implementation calls {@link #initStrategies}.
*/
//刷新策略
@Override
protected void onRefresh(ApplicationContext context) {initStrategies(context);
}/*** Initialize the strategy objects that this servlet uses.* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
//初始化各类解析器
protected void initStrategies(ApplicationContext context) {initMultipartResolver(context); //初始化分段上传解析器initLocaleResolver(context); //初始化地域解析器initThemeResolver(context); //初始化主题解析器initHandlerMappings(context); //初始化处理器映射initHandlerAdapters(context); //初始化处理器适配器initHandlerExceptionResolvers(context); //初始化处理器异常解析器initRequestToViewNameTranslator(context); //初始化请求到视图名解析器initViewResolvers(context); //初始化视图解析器initFlashMapManager(context); //初始化快闪映射
}
FrameworkServlet
onRefresh(ApplicationContext context)重写于父类FrameworkServlet,点开FrameworkServlet,我们主要看看它initServletBean()方法,FrameworkServlet的onRefresh(ApplicationContext context)是个空实现,因为在DispatcherServlet实现了。
initServletBean()是重写HttpServletBean的initServletBean(),先看看initServletBean()干了什么:
- 调用了initWebApplicationContext(),初始化了WebApplicationContext,而WebApplicationContext是继承于ApplicationContext接口的,所以我们知道了initWebApplicationContext是初始化了一个上下文。
- 调用了initFrameworkServlet(),点开发现是个空实现。
@Overrideprotected final void initServletBean() throws ServletException {//*******查看核心部分**********try {//这里初始化WebApplicationContextthis.webApplicationContext = initWebApplicationContext();initFrameworkServlet(); //空实现,给其他继承类实现}catch (ServletException | RuntimeException ex) {logger.error("Context initialization failed", ex);throw ex;}//*******其他日志的不看********}
点开initWebApplicationContext(),因为太长了,所以放图片。
上半段:
- 通过servlet上下文中创建了一个rootcontext
- 中间的if代码块在上下文刷新时才会运行,初始化状态时,webapplicationcontext是null,所以初始化时是不进入的。该段代码主要用于刷新上下文
下半段:
- 查找已经存在的注册的上下文,如果没有就用rootContex去创建一样上下文。
- refreshEventReceived默认是false
/** Flag used to detect whether onRefresh has already been called. */
private volatile boolean refreshEventReceived = false;
- onRefresh()方法被重写了,所以我们知道在Dispatchservlet中,会初始化各种解析器(如:视图解析器等)
HttpServletBean
假设WEB-INF 目录下查找配置文件信息如下:
<!-- 部署 DispatcherServlet -->
<servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!-- 表示容器再启动时立即加载servlet --><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>
HttpServletBean是抽象类,ctrl+F12查看方法。
找到init()方法,这个是我们要找到的重要方法
- init()方法是重写了GenericServlet的init()方法,所以这个是最根本的初始化方法。
让我们看看init()干了什么:
ServletConfigPropertyValues是用来加载Servlet配置,ServletConfigPropertyValues是HttpServletBean的内部静态类,它负责取到web.xml中init-param(如:contextConfigLocation)
@Overridepublic final void init() throws ServletException {//加载web.xml中init-param(如:contextConfigLocation)// Set bean properties from init parameters.PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);if (!pvs.isEmpty()) {try {//BeanWrapper将HttpServletBean进行包装BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);//ServletContext的资源加载器ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());//注册资源编辑器bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));//为HttpServletBean初始化包装,默认实现是空的initBeanWrapper(bw);//给包装类传递web.xml中init-parambw.setPropertyValues(pvs, true);}catch (BeansException ex) {if (logger.isErrorEnabled()) {logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);}throw ex;}}// Let subclasses do whatever initialization they like.//initServletBean()是交给子类实现的,FrameworkServlet实现了这个方法initServletBean();}
初始化总结
各类的初始化工作:
- HttpServletBean 主要初始化web.xml资源
- FrameworkServlet 获取servlet上下文创建WebApplicationContext
- DispatcherServlet 初始化各类解析器
调用过程
- HttpServletBean ---- init()
- FrameworkServlet ---- initServletBean()
- FrameworkServlet ---- initWebApplicationContext()
- DispatcherServlet ---- onRefresh(ApplicationContext context)
- DispatcherServlet ---- initStrategies(ApplicationContext context)
- DispatcherServlet ---- initXXX(ApplicationContext context)各种解析器组件的初始化
DispatcherServlet处理请求
核心成员变量
DispatcherServlet的核心成员变量就是上面DispatcherServlet初始化中initStrategies(ApplicationContext context)
初始化的各类处理器。
/** MultipartResolver used by this servlet. */@Nullableprivate MultipartResolver multipartResolver;/** LocaleResolver used by this servlet. */@Nullableprivate LocaleResolver localeResolver;/** ThemeResolver used by this servlet. */@Nullableprivate ThemeResolver themeResolver;/** List of HandlerMappings used by this servlet. */@Nullableprivate List<HandlerMapping> handlerMappings;/** List of HandlerAdapters used by this servlet. */@Nullableprivate List<HandlerAdapter> handlerAdapters;/** List of HandlerExceptionResolvers used by this servlet. */@Nullableprivate List<HandlerExceptionResolver> handlerExceptionResolvers;/** RequestToViewNameTranslator used by this servlet. */@Nullableprivate RequestToViewNameTranslator viewNameTranslator;/** FlashMapManager used by this servlet. */@Nullableprivate FlashMapManager flashMapManager;/** List of ViewResolvers used by this servlet. */@Nullableprivate List<ViewResolver> viewResolvers;
doService()
在浏览器输入位置时,会触发DispatcherServlet
的doService(HttpServletRequest request, HttpServletResponse response)
去处理请求。
doService(HttpServletRequest request, HttpServletResponse response)
又会去调用doDispatch(HttpServletRequest request, HttpServletResponse response)
去处理请求
doDispatch()
doDispatch比较多代码分成两段截图
上半段代码
下半段代码
还有
getHandler()
getHandler()会遍历所有的handlerMapping,并找出匹配的handler。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {for (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;}
关于handlerMapping接口的实现类
handlerMapping接口的实现类有许多,RequestMappingHandlerMapping,该类用于创建@RequestMapping和@Controller注解的实例
spring mvc DispatcherServlet解读相关推荐
- Spring MVC DispatcherServlet改造为 CSE RestServlet 常见问题汇编
[摘要] 本文是使用CSE RestServlet替换Spring MVC DispatcherServlet常见问题汇总. 将Spring Boot的REST应用改造为CSE的REST应用的核心部分 ...
- spring mvc DispatcherServlet详解之三---request通过ModelAndView中获取View实例的过程
整个spring mvc的架构如下图所示: 上篇文件讲解了DispatcherServlet第二步:通过request从Controller获取ModelAndView.现在来讲解第三步:reques ...
- spring mvc DispatcherServlet详解之前传---FrameworkServlet
做项目时碰到Controller不能使用aop进行拦截,从网上搜索得知:使用spring mvc 启动了两个context:applicationContext 和WebapplicationCont ...
- spring mvc DispatcherServlet详解之二---request通过Controller获取ModelAndView过程
整个spring mvc的架构如下图所示: 上篇文件讲解了DispatcherServlet通过request获取控制器Controller的过程,现在来讲解DispatcherServletDisp ...
- spring mvc DispatcherServlet详解之一--request通过HandlerMaping获取控制器Controller过程
整个spring mvc的架构如下图所示: 现在来讲解DispatcherServletDispatcherServlet的第一步:获取控制器. HandlerMapping HandlerMappi ...
- spring mvc DispatcherServlet详解之四---视图渲染过程
整个spring mvc的架构如下图所示: 现在来讲解DispatcherServletDispatcherServlet的最后一步:视图渲染.视图渲染的过程是在获取到ModelAndView后的过程 ...
- spring mvc DispatcherServlet详解之interceptor和filter的区别
首先我们看一下spring mvc Interceptor的功能及实现: http://wenku.baidu.com/link?url=Mw3GaUhCRMhUFjU8iIDhObQpDcbmmRy ...
- spring mvc DispatcherServlet详解之一---处理请求深入解析
要深入理解spring mvc的工作流程,就需要先了解spring mvc的架构: 从上图可以看到 前端控制器DispatcherServlet在其中起着主导作用,理解了DispatcherServl ...
- spring mvc DispatcherServlet详解之前传---前端控制器架构
前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端.前端控制器既可以使用Filter实现 ...
最新文章
- RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列
- bat常用命令操作符列表
- [裴礼文数学分析中的典型问题与方法习题参考解答]4.3.15
- leetcode 542. 01 Matrix | 542. 01 矩阵(图解,广度优先搜索)
- qpython3可以调用哪些库_Python3 如何使用asyncio库在调用第三方模块(存在IO等待)的情况下实现协程?...
- oracle 邮件过程,oracle 发邮件 存储过程
- 今天的出了校门的即时通讯
- 刑事科学技术专业与计算机专业,辽宁警察学院刑事科学技术专业
- 读写序列(pickle)
- 我的世界服务器领地怎么无限大,我的世界:Minecraft都市传说,MC无限大?让我们一起寻找边界吧...
- 数据分析常用名词解释
- 这座研究所出了8位菲尔兹奖得主: 教授没有发论文压力,不指定方向,不必教课...
- 2020年最全最好用的在线文档盘点,建议收藏
- 【博客园-问题反馈】使用谷歌浏览器 百度图床图片无法显示
- IGP LDP同步技术剖析
- CPU之外,国产芯片再突破,再也不用看AMD和NVIDIA的脸色了
- Android Things:让你陌生的面包板
- LeetCode简单-Python-(13)罗马数字转整数
- 进入外包公司之后…………
- 爬虫练习-荔枝直播(分享页)
热门文章
- Hyper-V下的Linux虚拟机网卡丢失问题原因及解决办法
- [转]MySQL数据库优化总结
- C#委托Action、ActionT、FuncT、PredicateT
- Asp.net(C#)动态生成表格中的按钮和事件响应
- SVM原理以及Tensorflow 实现SVM分类(附代码讲了一下原理)
- MySQL重要概念图解(重要)
- JS的window-location
- PHP的composer安装问题
- 佳能单反相机二次开发包介绍_家用单反相机什么牌子好
- 本地通过域名访问虚拟机的网站部署方法(Nginx)