【SpringMVC】之源码分析工作流程
一、概述
学习之后,记下笔记,理清思路。
带着问题去思考:
springMVC接收到用户请求之后,如何工作?
springMVC核心组件有哪些?
哪些是程序员需要编写的部分?
二、SpringMVC工作流程
工作流程:
- 用户发送请求;
- DispatcherSerlvet(前端控制器) 接收请求,调用HandlerMapping;
- HandlerMapping(处理器映射器) 去查找处理器Handler(就是Controller),HandlerMapping 返回执行链HandlerExecutionChain(包括Handler对象、拦截器数组)给DispatcherSerlvet;
- DispatcherSerlvet调用HandlerAdapter(处理器适配器);
- HandlerAdapter去执行Handler;
- Handler返回ModelAndView给HandlerAdapter;
- HandlerAdapter返回ModelAndView给DispatcherSerlvet;
- DispatcherSerlvet调用ViewResolver(视图解析器)进行视图解析;
- ViewResolver返回视图对象;
- DispatcherSerlvet进行视图渲染
- 返回渲染后对象;
- 响应请求。
三、核心组件
-
前端控制器DispatcherSerlvet
控制中心,接收请求,转发请求,响应请求
-
处理器映射器 HandlerMapping
查找处理器Handler
-
处理器适配器 HandlerAdapter
执行处理器Handler
-
视图解析器 ViewResolver
解析ModelAndView
-
处理器Handler (需要工程师开发)
Controller
-
视图View (需要工程师开发jsp...)
前端页面
四、源码分析
1、IDEA创建SpringMVC项目
参考:https://www.cnblogs.com/chenlinghong/p/8339555.html
创建出现的问题:
1 |
web.xml中出现“element servlet-name is not allow here”, 导致系统启动失败 |
修改schema,把原来的替换成
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
2 | 报错:org.apache.catalina.core.StandardContext.listenerStart Error configuring application listener of class org.springframework.web.context.ContextLoaderListener | 参考:https://www.cnblogs.com/feiyujun/p/6537510.html |
创建一个简单的SpringMVC项目,只关注SpringMVC的工作流程。
2、简单写个接口
@Controller @RequestMapping("/mvc") public class HelloWorldController { @RequestMapping("helloWorld") public String hello(){ return "helloWorld"; } }
3、分析DispatcherServlet
思路:DispatcherServlet继承FrameworkServlet,就是servlet,
servlet分:初始化,处理方法,销毁方法
核心就是service,
(下图是FrameworkServlet中的service方法)
再看关键的processRequest方法
点进去一看,是个抽象方法
那DispatcherServlet肯定重写了该方法
//DispatcherServlet.java
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if(this.logger.isDebugEnabled()) { String attributesSnapshot = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult()?" resumed":""; this.logger.debug("DispatcherServlet with name \'" + this.getServletName() + "\'" + attributesSnapshot + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]"); } HashMap attributesSnapshot1 = null; if(WebUtils.isIncludeRequest(request)) { attributesSnapshot1 = new HashMap(); Enumeration inputFlashMap = request.getAttributeNames(); label108: while(true) { String attrName; do { if(!inputFlashMap.hasMoreElements()) { break label108; } attrName = (String)inputFlashMap.nextElement(); } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet")); attributesSnapshot1.put(attrName, request.getAttribute(attrName)); } } request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource()); FlashMap inputFlashMap1 = this.flashMapManager.retrieveAndUpdate(request, response); if(inputFlashMap1 != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap1)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); try { this.doDispatch(request, response); //关键方法 } finally { if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot1 != null) { this.restoreAttributesAfterInclude(request, attributesSnapshot1); } } }
再看doDispatch,做了啥,看见了关键词getHandler、getHandlerAdapter
getHandler,返回 HandlerExecutionChain
getHandlerAdapter,返回 HandlerAdapter
4、调用getHandler,获取HandlerExecutionChain
在上面的两个方法上打断点,
this.handlerMappings 有三个元素
this.handlerMappings有三种类型,根据request请求使用不同的HandlerMapping
-
RequestMappingHandlerMapping
(支持带@RequestMapping
注释的方法) -
BeanNameUrlHandlerMapping
-
SimpleUrlHandlerMapping
(维护URI路径模式到处理程序的显式注册)。
返回handler(一个HandlerExecutionChain对象,包含了处理器controller和一个或多个拦截器),对应DispatcherServlet中的mappedHandler
4、调用getHandlerAdapter,获取HandlerAdapter
this.handlerAdapters有三种
- HttpRequestHandlerAdapter
- SimpleControllerHandlerAdapter
- RequestMappingHandlerAdapter
遍历所有类型,判断是否支持当前处理器handler
匹配RequestMappingHandlerAdapter,返回
进行到这一步,真正执行我们编写的处理器(Controller)
返回ModelAndView
后面还有视图解析。