【Spring】SpringMVC框架流程图及源码解析

一、SpringMVC简介

MVC模式全称Model----View----Controller即模型视图控制器模式。将模型和视图通过控制器进行分离。
Model:JavaBean,实体类,DAO,service
View:页面(html,jsp,thymeleaf,freemarker)
Controller:Servle

SpringMVC是一种基于 Java 实现了MVC 设计模型的请求驱动类型的轻量级 Web 框架,简化了Servlet开发过程。采用了一个核心的Servlet来处理所有的用户请求,是对Servlet封装(是MVC的C层),然后再调用Spring中的Action将请求进行处理。

个人认为SpringMVC超越Struts2,是目前最优秀的 MVC 框架。它能通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口,并且它还支持 RESTful 编程风格的请求。解决代码冗余问题,充分体现了聚合思想,可维护性高。但由SpringMVC的核⼼是Servlet,因此每个业务都需要有⼀个Servlet来执⾏,这样会导致过多的Servlet在使⽤内存,会导致内存不⾜(Servlet是单例多线程Servlet⽣命周期是第⼀次调⽤创建,容器关闭的时候才回收Servlet),因此需要对Web服务器的线程池进行优化来提升性能。
SpringMVC官方文档.

二、SpringMVC组件说明

  • DispatcherServlet:前端控制器
    前端控制器用户请求到达前端控制器,它就相当于mvc模式中的c,DispatcherServlet是整个流程控制的中心,由它doDispatch()方法调用其它组件处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合性。
  • HandlerMapping:处理器映射器
    处理器映射器HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
  • HandlerAdapter:处理器适配器
    通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
  • ViewResolver:视图解析器
    View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
  • Handler:处理器
    是DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。

在org.springframework.web.servlet目录下DispatcherServlet.properties文件中有设置SpringMvc默认加载的组件

三、SpringMVC的执行流程

在这里插入图片描述

  1. 前端控制器DispatcherServlet类实现doSerice()方法获取用户发送请求,并将其委托给doDispatch以进行调度
  2. doDispatch收到请求通过getHandler()调度HandlerMapping处理器映射器创建HandlerExecutionChain实例对象
    HandlerMapping处理器映射器接口,由AbstractHandlerMapping实现getHandler方法,通过getHandler方法调用getHandlerExecutionChain方法创建HandlerExecutionChain实例对象
  3. doDispatch调度getHandlerAdapter()方法获取HandlerAdapter处理器适配器调用合适的处理器
  4. 调度HandlerExecutionChain类的applyPreHandle()方法调用拦截器的PreHandle()
  5. 调度处理器适配器执行handle()方法,返回mv(即ModelAndView)
    处理器适配器的handle()方法通过HandlerAdapter接口由AnnotationMethodHandlerAdapter类的handle()方法实现,handle()方法调用invokeHandlerMethod()方法并通过ServletHandlerMethodInvoker调用getModelAndView()方法,通过内部反射调用ModelAttribute.class和handlerMethod准备参数反射执行(即controller),最后返回ModelAndView。
  6. 调度HandlerExecutionChain类的applyPostHandle()方法调用拦截器的PostHandle()
  7. 调度processDispatchResult()方法处理调度结果
    processDispatchResult()调用render()方法,render()方法通过resolveViewName()进行解析,resolveViewName()实际调用的是viewResolver视图解析器的resolveViewName()方法进行解析,由于ModelAndView对象包含实际的View对象,无需解析直接通过mv.getView()获取View,并直接通过view.render()进行渲染转发。
  8. 转发成功后通过triggerAfterCompletion()方法调用拦截器afterCompletion()

四、SpringMVC源码解读

下列代码块代码均为doDispatch()方法下,为了博文其简洁性在此只贴出DispatcherServlet类下的方法,如有错误,请指认留言,在此表示感谢!

  • DispatcherServlet类的路径图
    在这里插入图片描述
  1. DispatcherServlet类实现doSerice()方法获取请求属性,并将其委托给doDispatch以进行实际的调度
    在这里插入图片描述

  2. 确定当前请求的处理器
    HandlerExecutionChain 包含了处理器对象(Handler)以及和处理器拦截器(HandlerInterceptors)。

    940	|	mappedHandler = getHandler(processedRequest);
    

    通过getHandler()方法调用处理器映射器HandlerMapping接口获取HandlerExecutionChina对象
    在这里插入图片描述
    HandlerMapping接口由AbstractHandlerMapping实现getHandler方法
    通过getHandler方法调用getHandlerExecutionChain方法创建HandlerExecutionChain实例对象

  3. 确定当前请求的处理器适配器

    947	|	HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    

    getHandlerAdapter()方法
    在这里插入图片描述

  4. 调用拦截器的PreHandle方法
    通过HandlerExecutionChain类的applyPreHandle()方法调用拦截器的PreHandle()

    962	|	if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    963	|			return;
    964	|		}
    
  5. 实际调用处理器
    调用处理器适配器HandlerAdapter执行handle()方法返回mv(即ModelAndView)

    967	|	mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    

    handle()方法通过HandlerAdapter接口由AnnotationMethodHandlerAdapter类的handle()方法实现
    handle()方法调用invokeHandlerMethod()方法并通过ServletHandlerMethodInvoker调用getModelAndView()方法
    getModelAndView()方法通过内部反射调用ModelAttribute.class和handlerMethod准备参数反射执行(即controller)

  6. 调用拦截器的PostHandle方法
    通过HandlerExecutionChain类的applyPostHandle()方法调用拦截器的PostHandle()

    974	|	mappedHandler.applyPostHandle(processedRequest, response, mv);
    
  7. 处理调度结果

    984	|	processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    

    调用processDispatchResult()方法
    在这里插入图片描述
    调用render()方法进行视图解析并渲染转发
    resolveViewName()实际调用的是viewResolver视图解析器的resolveViewName()方法进行解析
    在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值