###0.前言
《Java EE互联网轻量级框架整合开发——SSM框架(Spring MVC+Spring+MyBatis)和Redis实现》
本文主要记录SpringMVC的处理流程,以便理解SpringMVC框架。
###1.DispactherServlet初始化流程
继承关系(父类->子类):HttpServlet -> HttpServletBean -> FramenworkServlet -> DispactherServlet
- HttpServlet:Web容器提供的抽象类,可载入Web容器中
- HttpServletBean:SpringMVC框架提供
- FramenworkServlet:SpringMVC框架提供,初始化Spring Web Ioc容器
- DispactherServlet:SpringMVC框架提供,初始化核心组件
DispactherServlet的初始化流程:
- HttpServletBean:
init()
->initServletBean()
(空方法,子类覆写); - FramenworkServlet:
initServletBean()
->initWebApplicationContext()
->onRefresh(context)
(空方法,子类覆写) - DispactherServlet:
onRefresh(context)
->initStrategies(context)
组件的初始化:
//DispatcherServlet类
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
- MultipartResolver:文件解析器,用于支持服务器文件上传
- LocaleResolver:国际化解析器,提供国际化支持
- ThemeResolver:主题解析器,提供主题切换功能
- HandlerMapping:处理器映射器,存放用户提供的处理器(handler)和对应的多个拦截器(HandlerInterceptor)
- HandlerAdapter:处理器适配器,用于适配和执行处理器的方法。
- SimpleControllerHandlerAdapter:控制器适配器(Controller接口)
- HttpRequestHandlerAdapter:普通请求适配器(HttpRequestHandler接口)
- HandlerExceptionResolver:处理器异常解析器,对处理器发生的异常进行处理(指定跳异常页等)
- RequestToViewNameTranslator:视图逻辑名称转换器,将视图名称转化为实际的视图
- ViewResolver:视图解析器,把逻辑视图解析为实际视图
- FlashMapManager:Flash开发管理器
###2.DispactherServlet的执行流程
- FrameworkServlet:
processRequest(request, response)
->doService(request, response)(抽象方法,具体实现由子类完成)
和publishRequestHandledEvent(...)(处理完成,响应用户)
- DispactherServlet:
doService(request, response)
->doDispatch(request, response)(分派各个组件)
doDispatch的代码:
//DispatcherServlet类
/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
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); //1.多部分请求实体检测,多文件上传
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest); //2. 获取处理器,返回HandlerExecutionChain
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
//3.根据handler获取合适的适配器
// Determine handler adapter for the current request.
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;
}
}
//额外处理1. 处理拦截器,实际调用interceptor.preHandle(...),异常直接triggerAfterCompletion(...)结束
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//4.通过处理器适配器执行处理器方法,返回逻辑视图(ModelAndView)
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//5.设置ModelAndView对应的viewName,使用ViewNameTranslator
applyDefaultViewName(processedRequest, mv);
//额外处理2. 处理拦截器,实际调用interceptor.postHandle(...)
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);
}
//5.渲染视图->render(...)->view.render(mv.getModelInternal(), request, response);
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);
}
}
}
}
通过源码可以知道,在获取请求(Request)后,最终是由DispatcherServlet
的doDispatch
方法进行处理。而doDispatch
方法将请求(Request)根据流程分派给各个组件处理,最终返回响应实体(Response)到父类FrameworkServlet
的publishRequestHandledEvent(...)
处理。
doDispatch的步骤:
- processRequest处理请求(FrameworkServlet)
- 多部分请求实体检测,多文件上传
- 获取处理器,返回HandlerExecutionChain(包含一个Handler和多个拦截器interceptor)
- 根据handler获取合适的适配器(handler可能是Controller)
- 通过处理器适配器执行处理器方法,返回逻辑视图(ModelAndView)
- 渲染视图->render(…)->view.render(mv.getModelInternal(), request, response)
- publishRequestHandledEvent处理Response,响应用户(FrameworkServlet)
###3.总结
SpringMVC的核心功能主要体现在DispactherServlet
类中,由DispactherServlet
分派任务给各个组件。而作为开发者,需要完成的便是这些组件的配置,和执行器Handler(Controller)
以及拦截器interceptor
的编写。
END
– Nowy
– 2018.12.19