在之前
Spring MVC DispatcherServlet的启动以及初始化 中介绍了
DispatcherServlet的启动过程,通过这个过程中建立琪了与DispatcherServlet相关的ioc容器环境,并进行了必要的MVC模块初始化工作,为处理请求做好了准备。下面说明DispatcherServlet另一个重要的功能,就是处理web请求。
1、DispatcherServlet类继承体系
以上类图主要反映
DispatcherServlet为处理web请求设计的相关类的继承体系,,可以看到,FrameworkServlet通过继承HttpServletBean而继承了HttpSerbvlet,在HttpSerbvlet实现了void service(HttpServletRequest request, HttpServletResponse response)方法处理web请求,而FrameworkServlet重写了这个方法,除此之外还重写了doGet()和doPost()等方法。最终都将请求调用DispatcherServlet的doDispatcher()方法,doDispatche()是SpringMVC处理web请求的核心方法,在该方法中充分体现DispatcherServlet前置处理器的功能,将主要说明。
2、SpringMVC模式架构
以上架构实现主要在
doDispatcher()方法中体现,
核心架构的具体流程步骤如下:
- 1、 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
- 2、 DispatcherServlet——>HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
- 3、 DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
- 4、 HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
- 5、 ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
- 6、 View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
- 7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
注: 此部分内容参考自互联网
3、SpringMVC请求处理具体流程
在MVC框架初始化完成后,对Http的请求处理是在doService()方法中完成,
doService()方法在DispatcherServlet类中:
doDispatch()函数是DispatcherServlet完成dispatcher的核心方法,在该方法中通过HandlerMapping获取请求所对应的handler,之后选择合适的HandlerAdapter对handler进行适配,通过适配器调用handler相应的请求处理方法,并返回ModelAndView对象,通过ViewResolver对视图进行解析,得到View,最后通过View类渲染视图进行呈现。可以看到这里是SpringMVC模式的核心体现。@Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if (logger.isDebugEnabled()) { String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : ""; logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]"); } //这里对request请求参数进行快照保存 // Keep a snapshot of the request attributes in case of an include, // to be able to restore the original attributes after the include. Map<String, Object> attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap<String, Object>(); Enumeration<?> attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } } //这里将一些框架全局对象设置到request中,以便于handler和view中使用 // Make framework objects available to handlers and view objects. request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); try {//这里是doDispatcher()函数分发请求的入口 doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot); } } } }
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 {
//检查请求是否是multipart,像文件上传这些,如果是通过MultipartResolver进行解析
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//通过getHandler()方法,使用HandlerMapping完成请求到处理器的映射,获取到HandlerExecutionChain
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
//将获取到的Handler处理器进行适配,用响应的HandlerAdapter进行包装
// 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;
}
}
//如果设置了拦截器,那么在执行handler处理器方法处理之前,进行拦截器预处理
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//通过适配器调用执行处理器的相关功能处理方法,返回ModelAndView对象,包含视图和Model数据
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(request, mv);
//如果设置了拦截器,那么在执行handler处理器方法处理之后,进行拦截器后处理
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
//这里处理请求结果,在个函数中,将判断是否有dispatchException,如果有,将通过ExceptionResolver进行解析处理。然后由ViewResolver解析View ,最后对View进行渲染呈现视图
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 {
//如果请求是multipart,那么这里进行资源清理操作
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
继续来看processDispatchResult()函数:
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception { boolean errorView = false; //如果有异常发出,那么这里将通过processHandlerException()方法处理异常情况,注意返回值仍然是ModelAndView对象 if (exception != null) { if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); } else { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); mv = processHandlerException(request, response, handler, exception); errorView = (mv != null); } } //这里得到最终的ModelAndView,然后进行渲染,渲染函数见下面 // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isDebugEnabled()) { logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + "': assuming HandlerAdapter completed request handling"); } } if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } //这里如果设置有拦截器,那么在完成渲染、视图呈现后,进行拦截器AfterCompletion调用 if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } }
在渲染函数render中,主要通过ViewResolver完成视图解析获取对应的视图,然后通过View对象渲染呈现视图
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. Locale locale = this.localeResolver.resolveLocale(request); response.setLocale(locale); View view; if (mv.isReference()) { //由ViewResolver解析View // We need to resolve the view name. view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + getServletName() + "'"); } } else { // No need to lookup: the ModelAndView object contains the actual View object. view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name '" + getServletName() + "'"); } } // Delegate to the View object for rendering. if (logger.isDebugEnabled()) { logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'"); } try { //通过View完成视图在渲染,渲染时会把Model传入 view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'", ex); } throw ex; } }