SpringMVC执行流程
1.SpringMVC的流程
(1)请求先被DispatcherServlet(前端控制器)拦截处理
(2)调用doDispatch方法进行处理
(2.1)getHandler()根据当前的请求在HandlerMapping(处理映射器)中找到这个请求的映射信息,获取目标处理器类(handler)
(2.2)getHandlerAdapter()根据当前的处理器类,找到相应的HandlerAdaper(适配器)
(2.3)使用刚才得到的适配器执行目标方法【也就是controller中的方法】
(2.4)这个目标方法将返回一个ModelAndView对象,返回给DispatcherServlet
(2.5)根据这个对象传给ViewReslover视图解析器, ViewReslover解析后返回具体View。
(2.6)并可以在请求域中获取这个对象的数据(model)
源码:
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 {
//检查当前的请求是否是文件长传的请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 决定当前请求用那个处理器【也就是选择controller】
mappedHandler = getHandler(processedRequest);
//如果没有找到哪个处理器就会异常404
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 拿到执行这个类的适配器【反射工具,就是反射controller】
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 获取请求的方式【get.post】
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//利用适配器执行目标方法,这个将返回将封装成ModelAndView中
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//如果没有视图名称,给一个默认的视图名称
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
//根据ModelAndView转发到对应的页面,而且ModelAndView中的数据可以从请求域中获取
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", 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);
}
}
}
2.部分方法的实现细节:
getHandler实现细节:
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
handlerMappings:他保存了每一个处理器能处理哪些方法的映射信息
有三个Mappings:
ioc容器在启动创建Controller对象的时候扫描每个处理器都能处理什么请求,保存在HanderMapping中的handlermap属性中,下一次请求,就来看看哪个HanderMapping中有这个映射信息就行了。
getHandlerAdapter方法:
这个方法是根据处理器,选择能够执行这个处理器的适配器。
在这有四种Adapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
3.SpringMVC的九大组件
/** 文件长传解析器 */
@Nullable
private MultipartResolver multipartResolver;
/** 区域信息解析器,和国际化有关 */
@Nullable
private LocaleResolver localeResolver;
/** 主题解析器*/
@Nullable
private ThemeResolver themeResolver;
/** handle映射信息 */
@Nullable
private List<HandlerMapping> handlerMappings;
/**handle适配器*/
@Nullable
private List<HandlerAdapter> handlerAdapters;
/** 异常解析功能 */
@Nullable
private List<HandlerExceptionResolver> handlerExceptionResolvers;
/** 视图地址转换 */
@Nullable
private RequestToViewNameTranslator viewNameTranslator;
/** FlashMap的管理,SpringMVC中运行重定向携带数据的功能 */
@Nullable
private FlashMapManager flashMapManager;
/** 视图解析器 */
@Nullable
private List<ViewResolver> viewResolvers;
这些组件的初始化都是在initStrategies这个方法中实现的,初始化过程其实都是差不多的:
1.先去容器中找是否有该组件
2.如果有就用容器中的
3.如果没有就使用默认的组件配置【DispatcherServlet.properties中对其默认属性进行了配置】