第一步,通过web.xml的配置可以知道,用户访问url第一次先走到DispatchServlet,(默认你学过基本的java的Servlet开发)
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
DispatchServlet类重点阅读
//初始化HandlerMap private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { //解析xml的 映射关系后,存放到 handlerMapping 后面会用到 this.handlerMappings = new ArrayList(matchingBeans.values()); OrderComparator.sort(this.handlerMappings); } } else { try { HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class); this.handlerMappings = Collections.singletonList(hm); } catch (NoSuchBeanDefinitionException var3) { ; } } if (this.handlerMappings == null) { this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class); if (this.logger.isDebugEnabled()) { this.logger.debug("No HandlerMappings found in servlet '" + this.getServletName() + "': using default"); } } }
下图为断点观察效果
从上图看到,其实这个map就是从spring-mvc.xml文件中读取的不同类型的映射,标准映射、静态资源、拦截器映射等
//初始化Adapters private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; if (this.detectAllHandlerAdapters) { Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList(matchingBeans.values()); OrderComparator.sort(this.handlerAdapters); } } else { try { HandlerAdapter ha = (HandlerAdapter)context.getBean("handlerAdapter", HandlerAdapter.class); this.handlerAdapters = Collections.singletonList(ha); } catch (NoSuchBeanDefinitionException var3) { ; } } if (this.handlerAdapters == null) { this.handlerAdapters = this.getDefaultStrategies(context, HandlerAdapter.class); if (this.logger.isDebugEnabled()) { this.logger.debug("No HandlerAdapters found in servlet '" + this.getServletName() + "': using default"); } } }
然后,通过断点+源码玩起来了,我这里是通过一个接口测试的,
首先执行 doService方法
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if (this.logger.isDebugEnabled()) { String requestUri = urlPathHelper.getRequestUri(request); String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : ""; this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + requestUri + "]"); } Map<String, Object> attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { this.logger.debug("Taking snapshot of request attributes before include"); attributesSnapshot = new HashMap(); Enumeration attrNames = request.getAttributeNames(); label113: while(true) { String attrName; do { if (!attrNames.hasMoreElements()) { break label113; } attrName = (String)attrNames.nextElement(); } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet")); attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.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 { this.doDispatch(request, response); } finally { if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { return; } if (attributesSnapshot != null) { this.restoreAttributesAfterInclude(request, attributesSnapshot); } } }
做了一些判断和数据的初始化工作,这里不是核心逻辑就暂时跳过了,看
doDispatch方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null;//关键变量,注意观察 boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest != request; mappedHandler = this.getHandler(processedRequest, false);//额这里无语了点了好几层才找到最终获取的Handler if (mappedHandler == null || mappedHandler.getHandler() == null) { this.noHandlerFound(processedRequest, response); return; } HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());//获取对应的adaptor String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (this.logger.isDebugEnabled()) { String requestUri = urlPathHelper.getRequestUri(request); this.logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); } if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } try { mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//执行方法 } finally { if (asyncManager.isConcurrentHandlingStarted()) { return; } } this.applyDefaultViewName(request, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var28) { dispatchException = var28; } this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception var29) { this.triggerAfterCompletion(processedRequest, response, mappedHandler, var29); } catch (Error var30) { this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var30); } } finally { if (asyncManager.isConcurrentHandlingStarted()) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); return; } else { if (multipartRequestParsed) { this.cleanupMultipart(processedRequest); } } } }
获取handler
handler封装HandlerExecutionChain,从代码来看就是把拦截器相关信息补充进去
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler); chain.addInterceptors(this.getAdaptedInterceptors()); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); Iterator i$ = this.mappedInterceptors.iterator(); while(i$.hasNext()) { MappedInterceptor mappedInterceptor = (MappedInterceptor)i$.next(); if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } return chain; }
从handlerMap中获取Adaptors,
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Iterator i$ = this.handlerMappings.iterator(); HandlerExecutionChain handler; do { if (!i$.hasNext()) { return null; } HandlerMapping hm = (HandlerMapping)i$.next(); if (this.logger.isTraceEnabled()) { this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'"); } handler = hm.getHandler(request); } while(handler == null); return handler; }
执行adaptor,最后利用了反射执行代理类的方法
执行后的返回视图逻辑
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { modelFactory.updateModel(webRequest, mavContainer); if (mavContainer.isRequestHandled()) { return null; } else { ModelMap model = mavContainer.getModel(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model); if (!mavContainer.isViewReference()) { mav.setView((View)mavContainer.getView()); } if (model instanceof RedirectAttributes) { Map<String, ?> flashAttributes = ((RedirectAttributes)model).getFlashAttributes(); HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(HttpServletRequest.class); RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } return mav; } }
总结:url->dispatchServlet->doService->doDispatch->根据url,从handlerMap获取handler,然后根据handler获取adaptor,通过adaptor执行要运行的方法,然后返回页面或者接口数据(返回的逻辑没来得及细看)
在这里即使用到了工厂模式、代理模式、和适配器模式