本文会分析一下SpringMVC执行的流程,以及源码分析底层实现的原理
SpringMVC流程
文章图片
文章图片
文章图片
根据以上SpringMVC工作原理图,对其工作流程作如下总结
- 用户发送请求至前端控制器DispatcherServlet。
- DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
- DispatcherServlet调用HandlerAdapter处理器适配器。
- HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
- Controller执行完成返回ModelAndView。
- HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
- ViewReslover解析后返回具体View。
- DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
- DispatcherServlet响应用户。
文章图片
SpringMVC底层核心代码块分析
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
// 异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
// 1、检查文件上传请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request. 决定当前请求 用哪个处理器
// 2、根据当前请求 决定哪个类来处理
mappedHandler = getHandler(processedRequest);
// 3、如果没有找到哪个处理器(控制器) 可以处理请求抛异常
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}// Determine handler adapter for the current request.决定当前请求 用哪个适配器
// 4、拿到能执行这个类的所有方法的适配器(反射工具) AnnotationMethodHandlerAdapter(注解方法的适配器)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}// Actually invoke the handler.
// 5、适配器来执行目标方法:将目标方法完成后的返回值作为视图名 设置保存在ModelAndView中
// 目标方法无论怎么写,最终适配器执行完成以后 都会将执行后的信息封装成ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 使用默认的视图名请求的地址是什么 视图名就是什么
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
// 6、根据方法最终执行完成后封装的ModelAndView;转发到对应的页面,而且ModelAndView可以从请求域中获取
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
底层方法执行流程: 【SSM|SpringMVC运行流程 源码分析】? 1、所有的请求过来DispatcherServlet收到请求
? 2、调用doDispatch()方法进行处理
- 1)、getHandler() : 根据当前请求地址找到能处理这个请求的目标处理器类(处理器)
? 根据当前请求在HanlderMapping中找到这个请求的映射信息,获取到目标处理器类
- 2)、getHandlerAdapter() : 根据当前处理器类获取到能执行这个处理器方法的适配器
根据当前处理器类,找到当前类的HandlerAdapter(适配器)
- 3)、使用刚才获取的适配器执行目标方法(AnnotationMethodHandlerAdapter)执行目标方法 ? -
- 4)、目标方法执行后会返回一个ModelAndView对象 ? -
- 5)、根据ModelAndView的信息转发具体的页面,并可以在请求与中取出ModelAndView中的模型数据
- getHandler() 会返回目标处理器类的执行链 ?
- handlerMappings 处理器映射: 里面保存了每一个处理器能处理的那些请求的映射信息 ?
- handlerMap: ioc容器启动创建Controller对象的时候扫描每个处理器都能处理什么请求,保存在HandlerMapping的handlerMap属性中,下次请求过来 就来看哪个handlerMapping中有这个请求映射信息就行了
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" +getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
文章图片
? 4、如何找到目标处理器的适配器。要拿适配器才去执行目标方法
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
// 支持就返回
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
文章图片
文章图片
SpringMVC九大组件
/** 文件上传解析器 */
private MultipartResolver multipartResolver;
/** 区域信息解析器;
和国际化有关 */
private LocaleResolver localeResolver;
/** 主题解析器:强大的主题效果更换 */
private ThemeResolver themeResolver;
/** Handler映射信息: handlerMappings*/
private List handlerMappings;
/** Handler的适配器: handlerAdapters*/
private List handlerAdapters;
/** SpringMVC强大的异常解析功能;异常解析器 */
private List handlerExceptionResolvers;
/** 视图名称翻译 */
private RequestToViewNameTranslator viewNameTranslator;
/** FlashMap + Manager :SpringMVC中运行重定向携带数据的功能 */
private FlashMapManager flashMapManager;
/** 视图解析器: */
private List viewResolvers;
*/
private RequestToViewNameTranslator viewNameTranslator;
/** FlashMap + Manager :SpringMVC中运行重定向携带数据的功能 */
private FlashMapManager flashMapManager;
/** 视图解析器: */
private List viewResolvers;
推荐阅读
- =======j2ee|spring用注解实现注入的@resource,@autowired,@inject区别
- jar|springboot项目打成jar包和war包,并部署(快速打包部署)
- 数据库|效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中【附源代码下载】)...
- java人生|35K 入职华为Java开发那天,我哭了(这 5 个月做的一切都值了)
- Java毕业设计项目实战篇|Java项目:在线嘿嘿网盘系统设计和实现(java+Springboot+ssm+mysql+maven)
- 微服务|微服务系列:服务发现与注册-----Eureka(面试突击!你想了解的Eureka都在这里.持续更新中......)
- java|ApplicationListener和SpringApplicationRunListener的联系
- Spring|SpringSecurity--自定义登录页面、注销登录配置
- 性能|性能工具之 Jmeter 通过 SpringBoot 工程启动
- Mybatis知识小汇(7)——使用注解开发