本文会分析一下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底层代码流程图:
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);
}
}
}
}
底层方法执行流程:
1、所有的请求过来DispatcherServlet收到请求
2、调用doDispatch()方法进行处理
-
1)、getHandler() : 根据当前请求地址找到能处理这个请求的目标处理器类(处理器)
根据当前请求在HanlderMapping中找到这个请求的映射信息,获取到目标处理器类 -
2)、getHandlerAdapter() : 根据当前处理器类获取到能执行这个处理器方法的适配器
根据当前处理器类,找到当前类的HandlerAdapter(适配器) -
3)、使用刚才获取的适配器执行目标方法(AnnotationMethodHandlerAdapter)执行目标方法 -
-
4)、目标方法执行后会返回一个ModelAndView对象 -
-
5)、根据ModelAndView的信息转发具体的页面,并可以在请求与中取出ModelAndView中的模型数据
3、getHandler()细节:如何根据当前请求就能找到哪个类能来处理
- 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<HandlerMapping> handlerMappings;
/** Handler的适配器: handlerAdapters*/
private List<HandlerAdapter> handlerAdapters;
/** SpringMVC强大的异常解析功能;异常解析器 */
private List<HandlerExceptionResolver> handlerExceptionResolvers;
/** 视图名称翻译 */
private RequestToViewNameTranslator viewNameTranslator;
/** FlashMap + Manager :SpringMVC中运行重定向携带数据的功能 */
private FlashMapManager flashMapManager;
/** 视图解析器: */
private List<ViewResolver> viewResolvers;
*/
private RequestToViewNameTranslator viewNameTranslator;
/** FlashMap + Manager :SpringMVC中运行重定向携带数据的功能 */
private FlashMapManager flashMapManager;
/** 视图解析器: */
private List<ViewResolver> viewResolvers;