Spring源码阅读 - MVC
MVC
① 初始化阶段:
② 运行-Dispatcher阶段:
③ 运行-ViewResolver阶段:
PS :
DispatcherServlet:
- onRefresh()方法,触发额外组件的初始化(MVC 9大组件)
// MVC 1 : onRefresh方法负责注册额外的初始化组件
DispatcherServlet#onRefresh(ApplicationContext context):
initStrategies(context);
// MVC 1 : 初始化MVC 9大组件
protected void initStrategies(ApplicationContext context) {
//多文件上传的组件
initMultipartResolver(context);
//初始化本地语言环境
initLocaleResolver(context);
//初始化模板处理器
initThemeResolver(context);
//handlerMapping
initHandlerMappings(context);
//初始化参数适配器
initHandlerAdapters(context);
//初始化异常拦截器
initHandlerExceptionResolvers(context);
//初始化视图预处理器
initRequestToViewNameTranslator(context);
//初始化视图转换器
initViewResolvers(context);
//FlashMap管理器(用于重定向过程中保留参数)
initFlashMapManager(context);
}
- doService()方法,运行时入口
// MVC :运行时入口。
DispatcherServlet#doService():
doDispatch()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// MVC 2:获取到请求对应的处理器链(HandlerExecutionChain 封装了 controllerHandler + interceptors)
mappedHandler = getHandler(processedRequest);
// MVC 3. 用对应的HandlerAdapter获取HandlerMapping
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// A. 拦截器前置拦截方法(若前置方法存在返回值为fasle,则中止该请求)
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// MVC 4:Actually invoke the handler,返回结果视图对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 设置默认的viewname(当mv不含有view对象时)
applyDefaultViewName(processedRequest, mv);
// B. 拦截器后置拦截方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
// MVC 5:结果视图对象的处理
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
- HandlerAdapter.handle(),主业务调用逻辑
AbstractHandlerMethodAdapter#handle():
// MVC 4:Actually invoke the handler,返回结果视图对象
return handleInternal(request, response, (HandlerMethod) handler);
RequestMappingHandlerAdapter#handleInternal():
// MVC 5:反射执行method, 获得modelAndView
mav = invokeHandlerMethod(request, response, handlerMethod);
RequestMappingHandlerAdapter#invokeHandlerMethod():
// MVC 5:反射执行method, 获得modelAndView
invocableMethod.invokeAndHandle(webRequest, mavContainer);
ServletInvocableHandlerMethod#invokeAndHandle():
// MVC 5:反射执行method, 获得modelAndView
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// InvocableHandlerMethod#invokeForRequest():
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// MVC : 完成参数绑定
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
"' with arguments " + Arrays.toString(args));
}
// MVC : 反射调用方法
Object returnValue = doInvoke(args);
if (logger.isTraceEnabled()) {
logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
"] returned [" + returnValue + "]");
}
return returnValue;
}
- ModelAndView视图渲染及响应
DispatcherServlet#processDispatchResult():
// MVC : 如果出现异常,则由异常处理器处理异常并获得对应的MV
mv = processHandlerException(request, response, handler, exception);
// MVC 6 : 视图渲染并输出
render(mv, request, response);
DispatcherServlet#render():
// 当mv中不存在view对象时,会在handler之后被设置默认的viewName.
// MVC : 如果viewName存在,则通过viewName解析获取到view对象
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
// MVC 7 : 视图通过response渲染输出
view.render(mv.getModelInternal(), request, response);
// AbstractView#render():
public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
" and static attributes " + this.staticAttributes);
}
// 将所有需要输出的Model(数据项)合并到一起
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
// 设置一些reponse header
prepareResponse(request, response);
// MVC :正式输出
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
欢迎疑问、期待评论、感谢指点 -- kiqi,愿同您为友
-- 星河有灿灿,愿与之辉