一、总流程
用户发送请求至前端控制器DispatcherServlet。
DispatcherServlet收到请求,选择合适的HandlerMapping(处理器映射器)。
处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),找到的Handler和拦截器一起生成HandlerExecutionChain,返回给DispatcherServlet。
DispatcherServlet调用HandlerAdapter(处理器适配器)。
HandlerAdapter适配调用具体的Handler(Controller,也叫后端控制器)。
Handler执行完具体逻辑,返回ModelAndView。
HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet。
DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
ViewReslover解析后返回具体View,这个view不是完整的,仅仅是一个页面(视图)名字,且没有后缀名。
DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
DispatcherServlet响应用户。
二、加载配置文件 使用SpringMVC时,一般通过web.xml
文件配置Tomcat容器
、applicationContext.xml
文件配置spring IOC容器
、springmvc.xml
文件配置MVC容器
。
2.1、web.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns ="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation ="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version ="2.5" > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > <context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:applicationContext*.xml</param-value > </context-param > <servlet > <servlet-name > dispatcherServlet</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:springmvc.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > dispatcherServlet</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > </web-app >
2.2、springmvc.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:mvc ="http://www.springframework.org/schema/mvc" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd" > <context:component-scan base-package ="com.yrl.controller" /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name ="prefix" value ="/pages/" /> <property name ="suffix" value =".jsp" /> </bean > <mvc:annotation-driven /> </beans >
<mvc:annotation-driven/>
标签相当于同时配置RequestMappingHandlerMapping和RequestMappingHandlerAdapter
2.3、applicationContext.xml 1 2 3 4 5 6 7 8 9 10 11 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <context:component-scan base-package ="com.yrl.service" /> </beans >
基于Tomcat-8.5
进行分析
3.1、加载web.xml Tomcat
的StandardContext
组件在初始化启动时,会加载web.xml
配置文件,将web.xml
中配置的servlet、listener、fiter
进行创建
如上面配置的web.xml
将创建ContextLoaderListener
、DispatcherServlet
3.2、StandardContext Tomcat组件的初始化创建会产生相应的生命周期事件。
以下代码做过简化,详情请点击查看Tomcat篇。
1 2 3 4 5 6 7 8 public class StandardContext extends ContainerBase implements Context { protected synchronized void startInternal () throws LifecycleException { listenerStart(); loadOnStartup(findChildren()) } }
3.2.1、listenerStart 启动对应监听器,初始化IOC容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class StandardContext extends ContainerBase implements Context { public boolean listenerStart () { Object instances[] = getApplicationLifecycleListeners(); ServletContextEvent event = new ServletContextEvent(getServletContext()); for (Object instance : instances) { if (!(instance instanceof ServletContextListener)) { continue ; } ServletContextListener listener = (ServletContextListener) instance; listener.contextInitialized(event); } } return ok; } }
3.2.2、loadOnStartup 加载并初始化Servlet
1 2 3 4 5 6 7 8 public class StandardContext extends ContainerBase implements Context { public boolean loadOnStartup (Container children[]) { wrapper.load(); } }
3.3、总结 3.3.1、ContextLoaderListener StandardContext组件初始化启动,会调用ontextLoaderListener
的contextInitialized(event)
方法发送ServletContextEvent
事件,此处会创建刷新IOC容器。
3.3.2、DispatcherServlet 加载web.xml
中指定<load-on-startup>
属性的Servlet,即我们配置的DispatcherServlet,初始化MVC相关组件。
基于spring-webmvc-5.2.15
进行分析
4.1、IOC容器 4.1.1、ContextLoaderListener ContextLoaderListener 接收ServletContextEvent 事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class ContextLoaderListener extends ContextLoader implements ServletContextListener { @Override public void contextInitialized (ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); } public WebApplicationContext initWebApplicationContext (ServletContext servletContext) { if (this .context == null ) { this .context = createWebApplicationContext(servletContext); } servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this .context); } }
4.1.2、创建IOC容器 当没有使用<context-param>
的contextClass
属性指定root WebApplicationContext的实现类时,默认实例化XmlWebApplicationContext 作为IOC容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 protected WebApplicationContext createWebApplicationContext (ServletContext sc) { Class<?> contextClass = determineContextClass(sc); if (!ConfigurableWebApplicationContext.class .isAssignableFrom (contextClass )) { throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]"); } return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); } protected Class<?> determineContextClass(ServletContext servletContext) { String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM); if (contextClassName != null ) { try { return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader()); } catch (ClassNotFoundException ex) { throw new ApplicationContextException( "Failed to load custom context class [" + contextClassName + "]" , ex); } } else { contextClassName = defaultStrategies.getProperty(WebApplicationContext.class .getName ()) ; try { return ClassUtils.forName(contextClassName, ContextLoader.class .getClassLoader ()) ; } catch (ClassNotFoundException ex) { throw new ApplicationContextException( "Failed to load default context class [" + contextClassName + "]" , ex); } } }
ContextLoader.properties配置文件 org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
4.1.3、配置并刷新IOC容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public class ContextLoaderListener extends ContextLoader implements ServletContextListener { @Override public void contextInitialized (ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); } public WebApplicationContext initWebApplicationContext (ServletContext servletContext) { if (this .context == null ) { this .context = createWebApplicationContext(servletContext); } if (this .context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this .context; if (!cwac.isActive()) { if (cwac.getParent() == null ) { ApplicationContext parent = loadParentContext(servletContext); cwac.setParent(parent); } configureAndRefreshWebApplicationContext(cwac, servletContext); } } servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this .context); return this .context; } protected void configureAndRefreshWebApplicationContext (ConfigurableWebApplicationContext wac, ServletContext sc) { wac.setServletContext(sc); String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM); if (configLocationParam != null ) { wac.setConfigLocation(configLocationParam); } customizeContext(sc, wac); wac.refresh(); } }
4.1.4、refresh 调用AbstractApplicationContext的refresh方法对应用上下文(IOC容器进)进行初始化,具体方法这不做介绍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 @Override public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } }
4.2、DispatcherServlet
4.2.1、初始化-Tomcat侧 由Tomcat源码分析可知,StandardContext
组件加载web.xml
,由于DispatcherServlet
配置<load-on-startup>
所以被StandardContext
提前实例化并初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class StandardWrapper extends ContainerBase implements ServletConfig , Wrapper , NotificationEmitter { @Override public synchronized void load () throws ServletException { instance = loadServlet(); if (!instanceInitialized) { initServlet(instance); } } private synchronized void initServlet (Servlet servlet) throws ServletException { servlet.init(facade); } } public abstract class GenericServlet implements Servlet , ServletConfig ,java .io .Serializable { @Override public void init (ServletConfig config) throws ServletException { this .config = config; this .init(); } public void init () throws ServletException { } }
以上是对Tomcat对Servlet的实例化和初始化
4.2.2、初始化-MVC侧 子类实现初始化 1 2 3 4 5 6 7 8 public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable , EnvironmentAware { @Override public final void init () throws ServletException { initServletBean(); } }
创建MVC容器 创建MVC容器,将ContextLoaderListener初始化创建的springIOC容器作为MVC容器的父容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { @Override protected final void initServletBean () throws ServletException { this .webApplicationContext = initWebApplicationContext(); initFrameworkServlet(); } protected WebApplicationContext initWebApplicationContext () { WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); if (wac == null ) { wac = createWebApplicationContext(rootContext); } if (!this .refreshEventReceived) { onRefresh(wac); } } protected WebApplicationContext createWebApplicationContext (WebApplicationContext parent) { return createWebApplicationContext((ApplicationContext) parent); } protected WebApplicationContext createWebApplicationContext (ApplicationContext parent) { ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); wac.setEnvironment(getEnvironment()); wac.setParent(parent); wac.setConfigLocation(getContextConfigLocation()); configureAndRefreshWebApplicationContext(wac); return wac; } }
初始化九大组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class DispatcherServlet extends FrameworkServlet { @Override protected void onRefresh (ApplicationContext context) { initStrategies(context); } protected void initStrategies (ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); } }
4.3、总结 Tomcat在初始化Web应用 时会通过事件监听器
进行IOC容器
的初始化,接着Tomcat在初始化Servlet
时,会通过Servlet
的init()
方法进行mvc容器
的初始化,并设置MVC容器与IOC容器的父子关系
4.4、DispatcherServlet.properties 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 org.springframework.web.servlet.LocaleResolver =org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver =org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping =org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\ org.springframework.web.servlet.function.support.RouterFunctionMapping org.springframework.web.servlet.HandlerAdapter =org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ org.springframework.web.servlet.function.support.HandlerFunctionAdapter org.springframework.web.servlet.HandlerExceptionResolver =org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator =org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator org.springframework.web.servlet.ViewResolver =org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager =org.springframework.web.servlet.support.SessionFlashMapManager
4.5、初始化HandlerMapping 初始化HandlerMapping,如果BeanFactory中没有,则从DispatcherServlet.properties
文件中获取默认实现,BeanNameUrlHandlerMapping
、RequestMappingHandlerMapping
、RouterFunctionMapping
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 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()) { this .handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values()); AnnotationAwareOrderComparator.sort(this .handlerMappings); } } else { try { HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class ) ; this .handlerMappings = Collections.singletonList(hm); } catch (NoSuchBeanDefinitionException ex) { } } if (this .handlerMappings == null ) { this .handlerMappings = getDefaultStrategies(context, HandlerMapping.class ) ; if (logger.isDebugEnabled()) { logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default" ); } } } protected <T> List<T> getDefaultStrategies (ApplicationContext context, Class<T> strategyInterface) { String key = strategyInterface.getName(); String value = defaultStrategies.getProperty(key); if (value != null ) { String[] classNames = StringUtils.commaDelimitedListToStringArray(value); List<T> strategies = new ArrayList<T>(classNames.length); for (String className : classNames) { try { Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class .getClassLoader ()) ; Object strategy = createDefaultStrategy(context, clazz); strategies.add((T) strategy); } catch (ClassNotFoundException ex) { throw new BeanInitializationException( "Could not find DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]" , ex); } catch (LinkageError err) { throw new BeanInitializationException( "Error loading DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]: problem with class file or dependent class" , err); } } return strategies; } else { return new LinkedList<T>(); } }
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping, org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
4.6、初始化HandlerAdapters 与初始化HandlerMapping类似。
初始化HandlerAdapter,如果BeanFactory中没有,则从DispatcherServlet.properties
文件中获取默认实现,HttpRequestHandlerAdapter
、SimpleControllerHandlerAdapter
、RequestMappingHandlerAdapter
、HandlerFunctionAdapter
。
五、HandlerMapping
5.1、初始化拦截器 Spring初始化HandlerMapping子类时,触发setApplicationContext方法,子类初始化拦截器(当通过getHandler方法时会将找到的handler与拦截器一起生成HandlerExecutionChain返回)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public abstract class ApplicationObjectSupport implements ApplicationContextAware { @Override public final void setApplicationContext (@Nullable ApplicationContext context) throws BeansException { if (context == null && !isContextRequired()) { } else if (this .applicationContext == null ) { this .applicationContext = context; this .messageSourceAccessor = new MessageSourceAccessor(context); initApplicationContext(context); } else { } } protected void initApplicationContext (ApplicationContext context) throws BeansException { initApplicationContext(); } } public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping , Ordered , BeanNameAware { @Override protected void initApplicationContext () throws BeansException { extendInterceptors(this .interceptors); detectMappedInterceptors(this .adaptedInterceptors); initInterceptors(); } }
5.2、BeanNameUrlHandlerMapping
初始化父类initApplicationContext,调用detectHandlers寻找匹配的handler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping { @Override public void initApplicationContext () throws ApplicationContextException { super .initApplicationContext(); detectHandlers(); } protected void detectHandlers () throws BeansException { ApplicationContext applicationContext = obtainApplicationContext(); String[] beanNames = (this .detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) : applicationContext.getBeanNamesForType(Object.class )) ; for (String beanName : beanNames) { String[] urls = determineUrlsForHandler(beanName); if (!ObjectUtils.isEmpty(urls)) { registerHandler(urls, beanName); } } if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) { logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName()); } } }
5.2.1、determineUrlsForHandler BeanNameUrlHandlerMapping实现determineUrlsForHandler方法,寻找bean的名称和别名以“/”开头的url。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping { @Override protected String[] determineUrlsForHandler(String beanName) { List<String> urls = new ArrayList<>(); if (beanName.startsWith("/" )) { urls.add(beanName); } String[] aliases = obtainApplicationContext().getAliases(beanName); for (String alias : aliases) { if (alias.startsWith("/" )) { urls.add(alias); } } return StringUtils.toStringArray(urls); } }
5.2.2、registerHandler 注册handler,建立url与handler的关系
1 2 3 4 5 6 7 8 9 10 11 public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping { private final Map<String, Object> handlerMap = new LinkedHashMap<>(); protected void registerHandler (String[] urlPaths, String beanName) throws BeansException, IllegalStateException { Assert.notNull(urlPaths, "URL path array must not be null" ); for (String urlPath : urlPaths) { registerHandler(urlPath, beanName); } } }
5.3、RequestMappingHandlerMapping 1 2 public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping <RequestMappingInfo > public abstract class AbstractHandlerMethodMapping <T > extends AbstractHandlerMapping implements InitializingBean
初始化 afterPropertiesSet springIOC容器初始化RequestMappingHandlerMapping时会调用InitializingBean的afterPropertiesSet方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements EmbeddedValueResolverAware { @Override public void afterPropertiesSet () { this .config = new RequestMappingInfo.BuilderConfiguration(); this .config.setPatternParser(getPathPatternParser()); this .config.setContentTypeResolver(getContentTypeResolver()); super .afterPropertiesSet(); } } public abstract class AbstractHandlerMethodMapping <T > extends AbstractHandlerMapping implements InitializingBean { @Override public void afterPropertiesSet () { initHandlerMethods(); int total = this .getHandlerMethods().size(); if ((logger.isTraceEnabled() && total == 0 ) || (logger.isDebugEnabled() && total > 0 ) ) { logger.debug(total + " mappings in " + formatMappingName()); } } }
initHandlerMethods 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public abstract class AbstractHandlerMethodMapping <T > extends AbstractHandlerMapping implements InitializingBean { protected void initHandlerMethods () { String[] beanNames = obtainApplicationContext().getBeanNamesForType(Object.class ) ; for (String beanName : beanNames) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { Class<?> beanType = null ; try { beanType = obtainApplicationContext().getType(beanName); } catch (Throwable ex) { if (logger.isTraceEnabled()) { logger.trace("Could not resolve type for bean '" + beanName + "'" , ex); } } if (beanType != null && isHandler(beanType)) { detectHandlerMethods(beanName); } } } handlerMethodsInitialized(getHandlerMethods()); } }
isHandler 判断当前bean是否可以作为handler,判定条件:被@Controller
或者 @RequestMapping
修饰
1 2 3 4 5 6 7 8 public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements EmbeddedValueResolverAware { @Override protected boolean isHandler (Class<?> beanType) { return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class ) || AnnotatedElementUtils .hasAnnotation (beanType , RequestMapping .class )) ; } }
detectHandlerMethods 寻找合适的HandlerMethod(被@RequestMapping修饰的方法)进行注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public abstract class AbstractHandlerMethodMapping <T > extends AbstractHandlerMapping implements InitializingBean { protected void detectHandlerMethods (final Object handler) { Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null ) { final Class<?> userType = ClassUtils.getUserClass(handlerType); Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> getMappingForMethod(method, userType)); if (logger.isTraceEnabled()) { logger.trace(formatMappings(userType, methods)); } methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); registerHandlerMethod(handler, invocableMethod, mapping); }); } } }
使用方法和类级别的@RequestMapping注解创建RequestMappingInfo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements EmbeddedValueResolverAware { @Override protected RequestMappingInfo getMappingForMethod (Method method, Class<?> handlerType) { RequestMappingInfo info = createRequestMappingInfo(method); if (info != null ) { RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); if (typeInfo != null ) { info = typeInfo.combine(info); } for (Map.Entry<String, Predicate<Class<?>>> entry : this .pathPrefixes.entrySet()) { if (entry.getValue().test(handlerType)) { String prefix = entry.getKey(); if (this .embeddedValueResolver != null ) { prefix = this .embeddedValueResolver.resolveStringValue(prefix); } info = RequestMappingInfo.paths(prefix).options(this .config).build().combine(info); break ; } } } return info; } @Nullable private RequestMappingInfo createRequestMappingInfo (AnnotatedElement element) { RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class ) ; RequestCondition<?> condition = (element instanceof Class ? getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element)); return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null ); } }
registerHandlerMethod 注册一个处理程序方法及其唯一的映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements EmbeddedValueResolverAware { @Override protected void registerHandlerMethod (Object handler, Method method, RequestMappingInfo mapping) { super .registerHandlerMethod(handler, method, mapping); updateConsumesCondition(mapping, method); } private void updateConsumesCondition (RequestMappingInfo info, Method method) { ConsumesRequestCondition condition = info.getConsumesCondition(); if (!condition.isEmpty()) { for (Parameter parameter : method.getParameters()) { MergedAnnotation<RequestBody> annot = MergedAnnotations.from(parameter).get(RequestBody.class ) ; if (annot.isPresent()) { condition.setBodyRequired(annot.getBoolean("required" )); break ; } } } } } public abstract class AbstractHandlerMethodMapping <T > extends AbstractHandlerMapping implements InitializingBean { protected void registerHandlerMethod (Object handler, Method method, T mapping) { this .mappingRegistry.register(mapping, handler, method); } class MappingRegistry { private final Map<T, MappingRegistration<T>> registry = new HashMap<>(); private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>(); private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>(); private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); public void register (T mapping, Object handler, Method method) { this .readWriteLock.writeLock().lock(); try { HandlerMethod handlerMethod = createHandlerMethod(handler, method); validateMethodMapping(handlerMethod, mapping); this .mappingLookup.put(mapping, handlerMethod); CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null ) { this .corsLookup.put(handlerMethod, corsConfig); } this .registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod)); } finally { this .readWriteLock.writeLock().unlock(); } } } }
六、HandlerAdapter 6.1、HttpRequestHandlerAdapter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Override public boolean supports (Object handler) { return (handler instanceof HttpRequestHandler); } @Override @Nullable public ModelAndView handle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((HttpRequestHandler) handler).handleRequest(request, response); return null ; } @Override public long getLastModified (HttpServletRequest request, Object handler) { if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L ; }
6.2、SimpleControllerHandlerAdapter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Override public boolean supports (Object handler) { return (handler instanceof Controller); } @Override @Nullable public ModelAndView handle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response); } @Override public long getLastModified (HttpServletRequest request, Object handler) { if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L ; }
6.3、RequestMappingHandlerAdapter AbstractHandlerMethodAdapter,HandlerAdapter实现的抽象基类,支持HandlerMethod类型的处理程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter , Ordered { public RequestMappingHandlerAdapter () { this .messageConverters = new ArrayList<>(4 ); this .messageConverters.add(new ByteArrayHttpMessageConverter()); this .messageConverters.add(new StringHttpMessageConverter()); try { this .messageConverters.add(new SourceHttpMessageConverter<>()); } catch (Error err) { } this .messageConverters.add(new AllEncompassingFormHttpMessageConverter()); } @Override public final boolean supports (Object handler) { return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); } @Override @Nullable public final ModelAndView handle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); } @Override public final long getLastModified (HttpServletRequest request, Object handler) { return getLastModifiedInternal(request, (HandlerMethod) handler); } }
handleInternal 使用指定的handler方法处理请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware , InitializingBean { @Override protected ModelAndView handleInternal (HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); if (this .synchronizeOnSession) { HttpSession session = request.getSession(false ); if (session != null ) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this .cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; } }
invokeHandlerMethod 调用RequestMapping的handler处理方法,返回一个ModelAndView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 @Nullable protected ModelAndView invokeHandlerMethod (HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); try { WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); if (this .argumentResolvers != null ) { invocableMethod.setHandlerMethodArgumentResolvers(this .argumentResolvers); } if (this .returnValueHandlers != null ) { invocableMethod.setHandlerMethodReturnValueHandlers(this .returnValueHandlers); } invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this .parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this .ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this .asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this .taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this .callableInterceptors); asyncManager.registerDeferredResultInterceptors(this .deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) { Object result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0 ]; asyncManager.clearConcurrentResult(); LogFormatUtils.traceDebug(logger, traceOn -> { String formatted = LogFormatUtils.formatValue(result, !traceOn); return "Resume with async result [" + formatted + "]" ; }); invocableMethod = invocableMethod.wrapConcurrentResult(result); } invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null ; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
invokeAndHandle 调用该方法并通过配置的HandlerMethodReturnValueHandlers处理返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class ServletInvocableHandlerMethod extends InvocableHandlerMethod { public void invokeAndHandle (ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); setResponseStatus(webRequest); if (returnValue == null ) { if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) { disableContentCachingIfNecessary(webRequest); mavContainer.setRequestHandled(true ); return ; } } else if (StringUtils.hasText(getResponseStatusReason())) { mavContainer.setRequestHandled(true ); return ; } mavContainer.setRequestHandled(false ); Assert.state(this .returnValueHandlers != null , "No return value handlers" ); try { this .returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(formatErrorForReturnValue(returnValue), ex); } throw ex; } } }
invokeForRequest 匹配支持的参数解析器,解析获取参数并调真实逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class InvocableHandlerMethod extends HandlerMethod { @Nullable public Object invokeForRequest (NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } return doInvoke(args); } }
handleReturnValue 匹配支持的返回值处理器,处理返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler { @Override public void handleReturnValue (@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType); if (handler == null ) { throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName()); } handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); } @Nullable private HandlerMethodReturnValueHandler selectHandler (@Nullable Object value, MethodParameter returnType) { boolean isAsyncValue = isAsyncReturnValue(value, returnType); for (HandlerMethodReturnValueHandler handler : this .returnValueHandlers) { if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue ; } if (handler.supportsReturnType(returnType)) { return handler; } } return null ; } }
getModelAndView 调用ModelFactory的updateModel方法更新model,包括设置SessionAttribute和给Model设置BinderResult
根据mavContainer创建了ModelAndView
如果mavContainer里的model是RedirectAttributes类型,则将其设置到FlashMap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware , InitializingBean { @Nullable private ModelAndView getModelAndView (ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { modelFactory.updateModel(webRequest, mavContainer); if (mavContainer.isRequestHandled()) { return null ; } ModelMap model = mavContainer.getModel(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (!mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } if (model instanceof RedirectAttributes) { Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class ) ; if (request != null ) { RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } } return mav; } }
7.1、Tomcat的Connector组件
初始化
创建CoyoteAdapter,用于将Tomcat请求响应对象适配为Servlet请求响应对象
NioEndpoint,基于NIO创建服务端端口监听
启动
创建Acceptor接收器、Poller轮询器
Acceptor接收客户连接
Poller处理读写事件
CoyoteAdapter将Tomcat请求响应对象适配为Servlet请求响应对象;
将请求、响应传到后面的组件处理,Container使用Pipeline-Valve管道来处理请求
寻找host
记录总结指定请求和响应的消息
输出HTML错误页面
匹配合适的Context处理
匹配合适的Wrapper处理
分配Servlet、构建过滤器链
调用servlet子类类service方法
7.2、HttpServlet HttpServlet调用service方法实现,最终调用子类实现的doXXX方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 public abstract class HttpServlet extends GenericServlet { @Override public void service (ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest) req; response = (HttpServletResponse) res; } catch (ClassCastException e) { throw new ServletException(lStrings.getString("http.non_http" )); } service(request, response); } protected void service (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1 ) { doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); } catch (IllegalArgumentException iae) { ifModifiedSince = -1 ; } if (ifModifiedSince < (lastModified / 1000 * 1000 )) { maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { String errMsg = lStrings.getString("http.method_not_implemented" ); Object[] errArgs = new Object[1 ]; errArgs[0 ] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } } }
7.3、FrameworkServlet doxxx方法最终都调用了processRequest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { @Override protected final void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } @Override protected final void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } protected final void processRequest (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null ; LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); LocaleContext localeContext = buildLocaleContext(request); RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.registerCallableInterceptor(FrameworkServlet.class .getName (), new RequestBindingInterceptor ()) ; initContextHolders(request, localeContext, requestAttributes); try { doService(request, response); } catch (Throwable ex) { } finally { resetContextHolders(request, previousLocaleContext, previousAttributes); if (requestAttributes != null ) { requestAttributes.requestCompleted(); } publishRequestHandledEvent(request, response, startTime, failureCause); } } private void publishRequestHandledEvent ( HttpServletRequest request, HttpServletResponse response, long startTime, Throwable failureCause) { if (this .publishEvents) { long processingTime = System.currentTimeMillis() - startTime; int statusCode = (responseGetStatusAvailable ? response.getStatus() : -1 ); this .webApplicationContext.publishEvent( new ServletRequestHandledEvent(this , request.getRequestURI(), request.getRemoteAddr(), request.getMethod(), getServletConfig().getServletName(), WebUtils.getSessionId(request), getUsernameForRequest(request), processingTime, failureCause, statusCode)); } } }
7.4、DispatcherServlet doService 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public class DispatcherServlet extends FrameworkServlet { @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) + "]" ); } 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(DEFAULT_STRATEGIES_PREFIX)) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } } 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 { doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { if (attributesSnapshot != null ) { restoreAttributesAfterInclude(request, attributesSnapshot); } } } } }
doDispatch
处理文件上传
通过handlerMappings,确定一个Handler,与拦截器一起封装成HandlerExecutionChain
寻找合适的HandlerAdapter
调用拦截器的前处理方法
实际调用,处理器适配器执行
调用拦截器的后处理方法
处理程序选择和调用的结果,要么是一个ModelAndView,要么是一个需要解析到ModelAndView的异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 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); mappedHandler = getHandler(processedRequest); if (mappedHandler == null ) { noHandlerFound(processedRequest, response); return ; } HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 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 ; } 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) { dispatchException = new NestedServletException("Handler dispatch failed" , err); } 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()) { if (mappedHandler != null ) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
handle 处理器适配器调用执行handler,具体参考-六、HandlerAdapter
processDispatchResult 处理返回结果,包括处理异常、渲染页面、触发Interceptor的afterCompletion
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class DispatcherServlet extends FrameworkServlet { 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 ); } } 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()) { return ; } if (mappedHandler != null ) { mappedHandler.triggerAfterCompletion(request, response, null ); } } }
render 渲染给定的模型和视图,这是处理请求的最后一个阶段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class DispatcherServlet extends FrameworkServlet { protected void render (ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { Locale locale = (this .localeResolver != null ? this .localeResolver.resolveLocale(request) : request.getLocale()); response.setLocale(locale); View view; String viewName = mv.getViewName(); if (viewName != null ) { view = resolveViewName(viewName, mv.getModelInternal(), locale, request); if (view == null ) { throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + getServletName() + "'" ); } } else { 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() + "'" ); } } if (logger.isTraceEnabled()) { logger.trace("Rendering view [" + view + "] " ); } try { if (mv.getStatus() != null ) { response.setStatus(mv.getStatus().value()); } view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "]" , ex); } throw ex; } } }
resolveViewName 默认情况下springmvc使用InternalResourceViewResolver
作为其视图解析器
调用视图解析器生成视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class DispatcherServlet extends FrameworkServlet { @Nullable protected View resolveViewName (String viewName, @Nullable Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception { if (this .viewResolvers != null ) { for (ViewResolver viewResolver : this .viewResolvers) { View view = viewResolver.resolveViewName(viewName, locale); if (view != null ) { return view; } } } return null ; } }
从缓存获取视图,不存在则创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public abstract class AbstractCachingViewResolver extends WebApplicationObjectSupport implements ViewResolver { @Override @Nullable public View resolveViewName (String viewName, Locale locale) throws Exception { if (!isCache()) { return createView(viewName, locale); } else { Object cacheKey = getCacheKey(viewName, locale); View view = this .viewAccessCache.get(cacheKey); if (view == null ) { synchronized (this .viewCreationCache) { view = this .viewCreationCache.get(cacheKey); if (view == null ) { view = createView(viewName, locale); if (view == null && this .cacheUnresolved) { view = UNRESOLVED_VIEW; } if (view != null && this .cacheFilter.filter(view, viewName, locale)) { this .viewAccessCache.put(cacheKey, view); this .viewCreationCache.put(cacheKey, view); } } } } else { if (logger.isTraceEnabled()) { logger.trace(formatKey(cacheKey) + "served from cache" ); } } return (view != UNRESOLVED_VIEW ? view : null ); } } }
创建视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered { @Override protected View createView (String viewName, Locale locale) throws Exception { if (!canHandle(viewName, locale)) { return null ; } if (viewName.startsWith(REDIRECT_URL_PREFIX)) { String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length()); RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible()); String[] hosts = getRedirectHosts(); if (hosts != null ) { view.setHosts(hosts); } return applyLifecycleMethods(REDIRECT_URL_PREFIX, view); } if (viewName.startsWith(FORWARD_URL_PREFIX)) { String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length()); InternalResourceView view = new InternalResourceView(forwardUrl); return applyLifecycleMethods(FORWARD_URL_PREFIX, view); } return super .createView(viewName, locale); } }
委托buildView创建指定视图类的新实例。
应用以下Spring生命周期方法(由通用Spring bean工厂支持):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public abstract class AbstractCachingViewResolver extends WebApplicationObjectSupport implements ViewResolver { @Nullable protected View createView (String viewName, Locale locale) throws Exception { return loadView(viewName, locale); } } public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered { @Override protected View loadView (String viewName, Locale locale) throws Exception { AbstractUrlBasedView view = buildView(viewName); View result = applyLifecycleMethods(viewName, view); return (view.checkResource(locale) ? result : null ); } }
buildView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class InternalResourceViewResolver extends UrlBasedViewResolver { @Override protected AbstractUrlBasedView buildView (String viewName) throws Exception { InternalResourceView view = (InternalResourceView) super .buildView(viewName); if (this .alwaysInclude != null ) { view.setAlwaysInclude(this .alwaysInclude); } view.setPreventDispatchLoop(true ); return view; } } public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered { protected AbstractUrlBasedView buildView (String viewName) throws Exception { Class<?> viewClass = getViewClass(); Assert.state(viewClass != null , "No view class" ); AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(viewClass); view.setUrl(getPrefix() + viewName + getSuffix()); view.setAttributesMap(getAttributesMap()); String contentType = getContentType(); if (contentType != null ) { view.setContentType(contentType); } String requestContextAttribute = getRequestContextAttribute(); if (requestContextAttribute != null ) { view.setRequestContextAttribute(requestContextAttribute); } Boolean exposePathVariables = getExposePathVariables(); if (exposePathVariables != null ) { view.setExposePathVariables(exposePathVariables); } Boolean exposeContextBeansAsAttributes = getExposeContextBeansAsAttributes(); if (exposeContextBeansAsAttributes != null ) { view.setExposeContextBeansAsAttributes(exposeContextBeansAsAttributes); } String[] exposedContextBeanNames = getExposedContextBeanNames(); if (exposedContextBeanNames != null ) { view.setExposedContextBeanNames(exposedContextBeanNames); } return view; } }
applyLifecycleMethods
1 2 3 4 5 6 7 8 9 10 11 12 13 public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered { protected View applyLifecycleMethods (String viewName, AbstractUrlBasedView view) { ApplicationContext context = getApplicationContext(); if (context != null ) { Object initialized = context.getAutowireCapableBeanFactory().initializeBean(view, viewName); if (initialized instanceof View) { return (View) initialized; } } return view; } }