赞
踩
SpringMVC的前端控制器(dispatcherServlet)本质就是一个Servlet,它接收并处理除了jsp页面之外的所有请求,其主要功能就是匹配并调用请求对应的controller控制器(处理器),并将控制器处理后的 ModelAndView(数据和视图) 进行渲染后响应给客户端
DispatcherServlet
继承于HTTPServlet
。当有请求发来时,首先执行HttpServlet
的doGet/doPost
方法,而FrameworkServlet
子类重写了doGet/doPost
方法,并在其中调用了processRequest
方法,而processRequest
方法中又调用了抽象方法doService
,该抽象方法是被DispatcherServlet
实现,并在其中调用了doDispatch
方法,doDispatch
方法便是前端控制器(DispathcerServlet) 的核心方法,以下是该方法的分析:
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); /** ②根据请求地址确定相应的控制器(处理器)映射对象 **/ // Determine handler for the current request. mappedHandler = getHandler(processedRequest); // ③如果没有找到对应的控制器来处理这个请求,则报404 if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } /** ④根据控制器映射对象确定对应的适配器,该适配器(反射工具)用于调用控制器方法 **/ // 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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } /** ⑥使用之前获取的适配器来调用控制器的业务方法,也就是Controller中的@RequestMapping方法, 并在执行完成后返回视图名。无论控制器业务方法中执行什么, 最终适配器调用完后的数据(模型和视图)都封装成ModelAndView **/ // Actually invoke the handler. 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处理转发的页面 **/ 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); } } } }
其中第②、④、⑥、⑧步为关键:
②:getHandler()
获取目标控制器
④:getHandlerAdapter()
获取执行目标控制器方法的适配器
⑥:handle()
使用适配器执行目标控制器方法
⑧:processDispatchResult
处理转发结果
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
是存放根据不同方式注册(xml配置和注解装配) 的处理器映射的集合。其中索引0为xml配置注册的,索引1为注解注册的(索引2暂时未知)。遍历handlerMappings
,找到其中保存有handler的元素(HandlerMapping)并返回。
而使用注解的处理器对象就是索引为1的
RequestMappingHandlerMapping
处理器映射
这个注解处理器映射对象中有一个
mappingRegistry
属性,便是存放使用@RequestMapping
注解配置的处理器的信息。在IOC容器启动创建Controller对象时,扫描每个处理器都能处理什么请求,并将这些处理器都保存在
mappingRegistry
属性中,以后发送的请求中,查找哪个HandlerMapping中有对应处理器即可。
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
此方法同上面的
getHandler()
一样,是遍历存放有不同注册方式的处理器对应的适配器,找到支持当前处理器对应的适配器
其中
RequestMappingHandlerAdapter
是通过注解注册的处理器对应的适配器,当遍历到它时,当前处理器会和它匹配然后返回这个适配器
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
通过适配器调用其抽象父类(AbstractHandlerMethodAdapter)的
handle
方法,其中又直接调用适配器(RequestMappingHandlerAdapter)的handleInternal()
方法
handleInternal()
{ ModelAndView mav; checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required. if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No HttpSession available -> no mutex necessary mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No synchronization on session demanded at all... mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
在
handleInternal()
方法中的第22行执行了invokeHandlerMethod(request, response, handlerMethod)
方法,此方法就是实际调用的处理器方法,得到处理后的ModelAndView并返回。
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { boolean errorView = false; 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); } } // 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.isTraceEnabled()) { logger.trace("No view rendering, null ModelAndView returned."); } } if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } if (mappedHandler != null) { // Exception (if any) is already handled.. mappedHandler.triggerAfterCompletion(request, response, null); } }
在第21行调用的
render()
方法,使用ModelAndView对转发的页面进行渲染
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。