【框架专题】管理型容器——SpringMVC源码

    技术2024-01-16  135

    SpringMVC源码——Tomcat内置MVC/IOC原理

    Tomcat——启动流程:

    Bootstrap: 作为 Tomcat 对外界的启动类,在 $CATALINA_BASE/bin 目录下,它通过用ClassLoader创建了Catlina实例; 的实例并对其进行初始化及启动。 Catalina: 解析 $CATALINA_BASE/conf/server.xml 文件并创建 StandardServer、StandardService、StandardEngine、StandardHost 等 将利用Digest解析server.xml(server的配置文件,server是最顶层容器),并根据server的配置文件创建server实例。 它通过 事件机制 实现各个容器间的内部通讯

    Tomcat——定制资源整合接口: (1)MyFacoryBean

    【StandardServer】---调用 【MyFacoryBean】 ---创建 【StandardContext】 public class MBeanFactory { public String createStandardContext(String parent, String path,String docBase) throws Exception { return createStandardContext(parent, path, docBase, false, false); } }

    (2) ContextConfig

    【MyCatoryBean】---创建 【ContextConfig】 ---调用【WebappServiceLoader】解析文件 public class ContextConfig implements LifecycleListener { protected final Map<ServletContainerInitializer, Set<Class<?>>> initializerClassMap = new LinkedHashMap<>(); public void lifecycleEvent(LifecycleEvent event) { try { context = (Context) event.getLifecycle(); } catch (ClassCastException e) { log.error(sm.getString("contextConfig.cce", event.getLifecycle()), e); return; } if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) { /* 此处激活配置初始化 */ configureStart(); } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) { beforeStart(); } else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) { if (originalDocBase != null) { context.setDocBase(originalDocBase); } } else if (event.getType().equals(Lifecycle.CONFIGURE_STOP_EVENT)) { configureStop(); } else if (event.getType().equals(Lifecycle.AFTER_INIT_EVENT)) { init(); } else if (event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)) { destroy(); } } protected synchronized void configureStart() { //…… webConfig(); //…… } protected void webConfig() { //…… //解析配置好的ServletContainerInitializer if (ok) { processServletContainerInitializers(); } //…… //…… //将ServletContainerInitializer加入conetxt中 if (ok) { for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :initializerClassMap.entrySet()) { if (entry.getValue().isEmpty()) { context.addServletContainerInitializer( entry.getKey(), null); } else { context.addServletContainerInitializer( entry.getKey(), entry.getValue()); } } } } protected void processServletContainerInitializers() { WebappServiceLoader<ServletContainerInitializer> loader = new WebappServiceLoader<>(context); detectedScis = loader.load(ServletContainerInitializer.class); for (ServletContainerInitializer sci : detectedScis) { initializerClassMap.put(sci, new HashSet<Class<?>>()); } } }

    (3)WebappServiceLoader

    【WebappServiceLoader,实例化这些Contanniner会发给Context存在在里面】 public class WebappServiceLoader<T> { private static final String LIB = "/WEB-INF/lib/"; private static final String SERVICES = "META-INF/services/"; /** * @META-INF/services加载指定文件中数据 * 扫描/META-INF/services/java.x.servlet.servletContainer的文件中的数据 * 一般就是ServletContainerInitializer的Class定位 */ public List<T> load(Class<T> serviceType) throws IOException { String configFile = SERVICES + serviceType.getName();//java.x.servlet.servletContainer try { parseConfigFile(applicationServicesFound, url); } catch (FileNotFoundException e) { } return loadServices(serviceType, containerServicesFound); } /** * @利用反射将字符串,变成类定位实例化他们 */ List<T> loadServices(Class<T> serviceType, LinkedHashSet<String> servicesFound) throws IOException { ClassLoader loader = servletContext.getClassLoader(); List<T> services = new ArrayList<>(servicesFound.size()); for (String serviceClass : servicesFound) { try { Class<?> clazz = Class.forName(serviceClass, true, loader); services.add(serviceType.cast(clazz.getConstructor().newInstance())); } catch (ReflectiveOperationException | ClassCastException e) { throw new IOException(e); } } return Collections.unmodifiableList(services); } }

    (4) StandardContext

    【StandardContext启动这些类,由这个生命周期启动】 上面已经解析了注解中类型,并利用反射将感兴趣的类也用实例化的方式传了进来; protected synchronized void startInternal() throws LifecycleException { for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :initializers.entrySet()) { try { entry.getKey().onStartup(entry.getValue(),getServletContext()); } catch (ServletException e) { log.error(sm.getString("standardContext.sciFail"), e); ok = false; break; } } }

    SpringMVC——定制资源:

    由StandtardContext暴露的addServletContainerInitializer,分别由ContextConfig和servlet工厂执行; 这些Initializer会注册监听器的形式,拿到事件以及上下文对象后setAddtirdute即

    (1)SpringServletContainerInitializer 主启动类(ServletContainerInitializer 一个实现类)

    利用HandlesTypes注解指定加载所有实现了子启动接口的启动类,tomcat用反射找到他们,传入webAppInitializerClasses =>=>=>但排除接口、抽象类 @HandlesTypes(WebApplicationInitializer.class) public class SpringServletContainerInitializer implements ServletContainerInitializer { public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException { ……………… servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath"); AnnotationAwareOrderComparator.sort(initializers); for (WebApplicationInitializer initializer : initializers) { initializer.onStartup(servletContext); } } }

    (2)WebApplicationInitializer通用父类的初始化

    AbstractDispatcherServletInitializer ——DispatcherServlet内置的getServletConfigClasses AbstractContextLoaderInitializer ——Context容器内置的getRootConfigClasses

    【onStartup回调结构】 public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer { public void onStartup(ServletContext servletContext) throws ServletException { super.onStartup(servletContext); registerDispatcherServlet(servletContext); } } public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer { protected final Log logger = LogFactory.getLog(getClass()); public void onStartup(ServletContext servletContext) throws ServletException { registerContextLoaderListener(servletContext); } } 【registerDispatcherServlet——创建子容器】 protected void registerDispatcherServlet(ServletContext servletContext) { /* 创建WebApplicationContext,注意不是StanderContext这是自定义的专用于WebApplicationContext 的上下文,我们后面再研究 */ String servletName = getServletName(); WebApplicationContext servletAppContext = createServletApplicationContext(); /* 添加dispatcherServlet,并指定ApplicationContextInitializers父类指定 */ FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext); dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers()); ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet); /* 添加过滤器 */ Filter[] filters = getServletFilters(); if (!ObjectUtils.isEmpty(filters)) { for (Filter filter : filters) { registerServletFilter(servletContext, filter); } } customizeRegistration(registration); } protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) { return new DispatcherServlet(servletAppContext); } } 某个WebApplicationContext举例 public abstract class AbstractAnnotationConfigDispatcherServletInitializer extends AbstractDispatcherServletInitializer { /* AnnotationConfigWebApplicationContext 通过getServletConfigClasses植入componentClasses,以用于某些开发 */ protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); Class<?>[] configClasses = getServletConfigClasses(); if (!ObjectUtils.isEmpty(configClasses)) { context.register(configClasses); } return context; } /* (1)先注册classes */ public void register(Class<?>... componentClasses) { Assert.notEmpty(componentClasses, "At least one component class must be specified"); Collections.addAll(this.componentClasses, componentClasses); } /* (2)实例化classes,有容器刷新调用 */ protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) { //…… if (!this.componentClasses.isEmpty()) { reader.register(ClassUtils.toClassArray(this.componentClasses)); } //…… } public void register(Class<?>... componentClasses) { for (Class<?> componentClass : componentClasses) { registerBean(componentClass); } } } 【registerContextLoaderListener——创建父容器】 protected void registerContextLoaderListener(ServletContext servletContext) { /* 创建一个根WebApplicationContext */ WebApplicationContext rootAppContext = createRootApplicationContext(); if (rootAppContext != null) { /* 创建监听器,这个监听器会在servletContext的时候调用 */ ContextLoaderListener listener = new ContextLoaderListener(rootAppContext); listener.setContextInitializers(getRootApplicationContextInitializers()); servletContext.addListener(listener); } else { logger.debug("No ContextLoaderListener registered, as " + "createRootApplicationContext() did not return an application context"); } } 某个WebApplicationContext举例,这些内置了大量bean原生ioc创建的细节 public class AnnotationConfigServletWebApplicationContext extends GenericWebApplicationContext implements AnnotationConfigRegistry { public AnnotationConfigServletWebApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } } public class GenericWebApplicationContext extends GenericApplicationContext implements ConfigurableWebApplicationContext, ThemeSource { public GenericWebApplicationContext() { super(); } } public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); } } /* 由StanderContext的生命周期取执行调用 */ public class ContextLoaderListener extends ContextLoader implements ServletContextListener { public void contextInitialized(ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); } } public class ContextLoader { public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {// StanderContext作为事件源传入 try { 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);//刷新 } } /* 以这个静态变量作为key设置当前的自定义上下文进去 */ servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); //…… } }

    (3)自定义WebAppInitializer

    public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { //父容器——registerContextLoaderListener return new Class<?>[]{IocConfig.class}; } protected Class<?>[] getServletConfigClasses() {//子容器——registerDispatcherServlet return new Class<?>[]{MvcConfig.class}; } protected String[] getServletMappings() { return new String[]{"/"}; } }

    (4)创建IOC容器

    利用Context监听器 创建上下文的时候=>getRootConfigClasses(排除Controller),并绑定自定义上下文到指定的key 监听回调的时候=>getRootApplicationContextInitializers,每个ContextInitializers会传入自定义的上下文

    @ComponentScan(value="com.atguigu",excludeFilters={ @Filter(type=FilterType.ANNOTATION,classes={Controller.class}) }) public class IocConfig { }

    (5)创建MVC容器

    利用DisPatcherServlet 创建自定义上下文的时候=>getServletConfigClasses 容器刷新的时候执行=>getServletApplicationContextInitializers,每个ContextInitializers会传入自定义的上下文

    @ComponentScan(value="com.atguigu",includeFilters={ @Filter(type=FilterType.ANNOTATION,classes={Controller.class}) },useDefaultFilters=false) @EnableWebMvc public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/views/", ".jsp"); } public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyFirstInterceptor()).addPathPatterns("/**"); } }

    (6)Servlet初始化(父子连接)

    public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable { public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); } } public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware { public final void init() throws ServletException { PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); if (!pvs.isEmpty()) { try { BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } catch (BeansException ex) { if (logger.isErrorEnabled()) { logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); } throw ex; } } initServletBean(); } } public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { protected final void initServletBean() throws ServletException { try { this.webApplicationContext = initWebApplicationContext(); initFrameworkServlet(); } catch (ServletException | RuntimeException ex) { logger.error("Context initialization failed", ex); throw ex; } } protected WebApplicationContext initWebApplicationContext() { /* 获取根容器rootContext */ WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; /* 设为父容器 */ if (this.webApplicationContext != null) { wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { if (cwac.getParent() == null) { cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } /* StanderContext上下文中添加自己 */ if (this.publishContext) { String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; } } /* 获取根容器rootContext的方法 */ public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); } /* 子容器key的方法 */ public String getServletContextAttributeName() { return SERVLET_CONTEXT_PREFIX + getServletName(); }

    SpringMVC源码——tomcat阶段请求调用管理

    Tomcat——请求调用整体流程

    【StandardEngine----StandardEngineValve】他用来将 Request 映射到指定的 Host 【StandardHost----StandardHostValve】Host代表Tomcat集群;利用Request 映射到指定的Context; 【StandardContext—StandardContextValve】Context代表分布式应用,它用来将 Request 映射到指定的 Wrapper 【StandardWrapper----StandardWrapperValve】Wrapper代表应用中的具体服务,他用来加载 Rquest 所指定的 Servlet

    Tomcat——协议适配处理流程:

    【StandardServer】 StandardServer 代表的是整个 Servlet 容器,他包含一个或多个 StandardService, StandardService中会创建连接器来处理sokcet端口的一切事务; 【connector连接器】 该连接器旗下的大量类会会在初始化方法中,启动所有线程池来进行端口监听、nio多路复用的线程等; 【ProtocollHandler】 容器初始化完成后,就是等待监听然后进行处理,以下就是资源-协议-业务的流程,以ProtocollHandler为首! 由ProtocollHandler下系列的子类负责具体执行不同的协议层组件 【Adapter组件】 由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request(org.apache.coyote.Request)类来“存放”这些请求信息 CoyoteAdapter 负责将 Tomcat Request 对象转成 ServletRequest,再调用容器的 Service 方法。这个方法是connector到container的入口 【Acceptor】 直接对外连接将socket通道对象,注册成为NIO通道对象; 【Poller】将socket通道对象,加入PollerEvent队列中,利用selector.select多路复用获取数据,最后将socket通道对象封装SocketProcessor 【SocketProcess】将请求被转移到handler.process;Http11ConnectionHandle 【Pieple流程】 进入容器container处理后,就要使用到容器的一个重要的结构:管道pipeline。每个容器类组件都有一个pipeline属性,这个属性控制请求的处理过程,在pipeline上可以添加Valve,进而可以控制请求的处理流程。可以将请求想象成水的流动,请求需要在各个组件之间流动,中间经过若干的水管和水阀,等所有的水阀走完,请求也就处理完了,而每个组件都会有一个默认的水阀(以Standard作为类的前缀)来进行请求的处理,如果业务需要的话,可以自定义Valve,将其安装到容器中。 【NioEndponit】 专用于处理sokcet流程的连接点

    SpringMVC源码——Servlet接口分析

    FrameworkServlet

    主要提供了一些ioc交互的接口

    public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { /* 执行一些自定义的Initializer,他会传入当前上下文让你操作 */ protected void applyInitializers(ConfigurableApplicationContext wac) { String globalClassNames = getServletContext().getInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM); if (globalClassNames != null) { for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) { this.contextInitializers.add(loadInitializer(className, wac)); } } if (this.contextInitializerClasses != null) { for (String className : StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS)) { this.contextInitializers.add(loadInitializer(className, wac)); } } AnnotationAwareOrderComparator.sort(this.contextInitializers); for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) { initializer.initialize(wac); } } /* 事件回调函数 */ public void onApplicationEvent(ContextRefreshedEvent event) { this.refreshEventReceived = true; synchronized (this.onRefreshMonitor) { onRefresh(event.getApplicationContext()); } } /* 再次调用一次刷新IOC容器 */ public void refresh() { WebApplicationContext wac = getWebApplicationContext(); if (!(wac instanceof ConfigurableApplicationContext)) { throw new IllegalStateException("WebApplicationContext does not support refresh: " + wac); } ((ConfigurableApplicationContext) wac).refresh(); } /* 发布ioc事件,激活另外的回调 */ private void publishRequestHandledEvent(HttpServletRequest request, HttpServletResponse response, long startTime, @Nullable Throwable failureCause) { if (this.publishEvents && this.webApplicationContext != null) { long processingTime = System.currentTimeMillis() - startTime; this.webApplicationContext.publishEvent( new ServletRequestHandledEvent(this, request.getRequestURI(), request.getRemoteAddr(), request.getMethod(), getServletConfig().getServletName(), WebUtils.getSessionId(request), getUsernameForRequest(request), processingTime, failureCause, response.getStatus())); } } }

    DispatcherServlet

    主要是调用一些mvc的组件比如拦截器、视图解析、适配器等,当然我们这里只暂时分心他的初始化

    public class DispatcherServlet extends FrameworkServlet { 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); } } private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; /* detectAllHandlerMappings为ture拿出多个HandlerMapping */ Handler if (this.detectAllHandlerMappings) { Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values()); AnnotationAwareOrderComparator.sort(this.handlerMappings); } } else { try { /* detectAllHandlerMappings为false, 利用HANDLER_MAPPING_BEAN_NAME拿出来唯一一个HandlerMapping */ HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class); this.handlerMappings = Collections.singletonList(hm); } catch (NoSuchBeanDefinitionException ex) { } } /* Bean中没有使用默认的策略 */ if (this.handlerMappings == null) { this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); if (logger.isTraceEnabled()) { logger.trace("No HandlerMappings declared for servlet '" + getServletName() + "': using default strategies from DispatcherServlet.properties"); } } }

    WebMvcConfigurationSupport

    SpringMVC中内置了WebMvcConfigurationSupport,为要定制MVC开发人员提供基础配置,SpringBoot则是利用AutoConfiguartion实现了这个WebMvcConfigurationSupport来定制MVC的基础配置;我们现在来分析一下以便于我们知道我们在DisPatcherServlet中的组件来自于哪里

    public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware { /* 异常解析器 */ protected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver() { return new ExceptionHandlerExceptionResolver(); } /* 请求适配器 */ protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() { return new RequestMappingHandlerAdapter(); } /* mapping第一层映射器 */ protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() { return new RequestMappingHandlerMapping(); } /* 消息转化默认配置 */ protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) { /* 基本类型数据的消息转化 */ messageConverters.add(new ByteArrayHttpMessageConverter()); messageConverters.add(new StringHttpMessageConverter()); messageConverters.add(new ResourceHttpMessageConverter()); messageConverters.add(new ResourceRegionHttpMessageConverter()); try { messageConverters.add(new SourceHttpMessageConverter<>()); } catch (Throwable ex) { } messageConverters.add(new AllEncompassingFormHttpMessageConverter()); /* 基本类型数据的消息转化 */ if (romePresent) { messageConverters.add(new AtomFeedHttpMessageConverter()); messageConverters.add(new RssChannelHttpMessageConverter()); } /* xml数据的消息转化 */ if (jackson2XmlPresent) { Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml(); if (this.applicationContext != null) { builder.applicationContext(this.applicationContext); } messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build())); } else if (jaxb2Present) { messageConverters.add(new Jaxb2RootElementHttpMessageConverter()); } /* json数据的消息转化 */ if (jackson2Present) { Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json(); if (this.applicationContext != null) { builder.applicationContext(this.applicationContext); } messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build())); } else if (gsonPresent) { messageConverters.add(new GsonHttpMessageConverter()); } else if (jsonbPresent) { messageConverters.add(new JsonbHttpMessageConverter()); } if (jackson2SmilePresent) { Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.smile(); if (this.applicationContext != null) { builder.applicationContext(this.applicationContext); } messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build())); } if (jackson2CborPresent) { Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.cbor(); if (this.applicationContext != null) { builder.applicationContext(this.applicationContext); } messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build())); } } /* 注入bean举例 */ @Bean @SuppressWarnings("deprecation") public RequestMappingHandlerMapping requestMappingHandlerMapping( @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager, @Qualifier("mvcConversionService") FormattingConversionService conversionService, @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) { RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping(); return mapping; } }

    WebMvcConfigurerAdapter

    用于扩展MVC的配置,用户可以实现这个接口轻松扩展拦截器,视图解析等配置

    @EnableWebMvc public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/views/", ".jsp"); } public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyFirstInterceptor()).addPathPatterns("/**"); } }

    RequestContextListener

    SpringMVC内置的请求监听器

    public class RequestContextListener implements ServletRequestListener { public void requestInitialized(ServletRequestEvent requestEvent) { HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest(); ServletRequestAttributes attributes = new ServletRequestAttributes(request); request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes); LocaleContextHolder.setLocale(request.getLocale()); /* 通过RequestContextHolder.getRequestAttributes()可以拿出这个数据,绑定了ThreadLocal里面了 */ RequestContextHolder.setRequestAttributes(attributes); } }

    SpringMVC源码——mvc阶段请求调用原理

    (1)获取处理器

    public class DispatcherServlet extends FrameworkServlet { protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { mappedHandler = getHandler(processedRequest); /* 直接返回404错误 */ if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } } }

    (1.1)一级处理器 (1.2)根据处理器获取执行链HandlerExecutionChain

    public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware { public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { /* 获取二级处理器,就是我们的controller */ Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } /* 拆解执执行链 */ HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); return executionChain; } }

    (1.3)获取二级处理器

    public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean { protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { /* 匹配二级处理器 addMatchingMappings */ List<Match> matches = new ArrayList<>(); List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { addMatchingMappings(directPathMatches, matches, request); } //…… if (!matches.isEmpty()) { Match bestMatch = matches.get(0); //…… request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); handleMatch(bestMatch.mapping, lookupPath, request); return bestMatch.handlerMethod; } else { return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } } private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) { for (T mapping : mappings) { T match = getMatchingMapping(mapping, request); if (match != null) { matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping))); } } } }

    (1.4)二级处理器核心数据

    class MappingRegistry { public Map<T, HandlerMethod> getMappings() { return this.mappingLookup; } }

    Ps:mappingLookup中包含了我们的一切,这就是二级处理器的核心数据;

    (1.5)获取执行链(adaptedInterceptors嵌入,拦截器)

    public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware { protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH); /* 遍历所有adaptedInterceptors,匹配的则将执行链添加其中 */ for (HandlerInterceptor interceptor : this.adaptedInterceptors) { if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; } }

    (2)获取适配器(内涵消息转化器)

    public class DispatcherServlet extends FrameworkServlet { protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { /* 获取适配器 */ 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; } /* 利用适配器执行业务 返回modelAnfView */ mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); /* 配置默认的视图名 */ 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); } } }

    (1.1)获取适配器

    针对于不同Controller类型做适配

    (1.2)执行结果处理

    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); } } /* 渲染视图 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."); } } /* 执行渲染后的AfterCompletion方法 */ if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); }

    (1.3)视图解析调用

    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) { // We need to resolve the view name. view = resolveViewName(viewName, mv.getModelInternal(), locale, request); } else { view = mv.getView(); } /* 渲染视图 */ 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; } } /* 用流将数据写成HTML发出去 */ private static class HtmlResourceView implements View { private Resource resource; HtmlResourceView(Resource resource) { this.resource = resource; } @Override public String getContentType() { return MediaType.TEXT_HTML_VALUE; } @Override public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { response.setContentType(getContentType()); FileCopyUtils.copy(this.resource.getInputStream(), response.getOutputStream()); } }

    SpringMVC源码——消息转化调用(待更新)

    SpringMVC源码——全局异常处理转发原理(待更新)

    SpringMVC源码——文件上传处理原理(待更新)

    SpringMVC源码——总结(待更新)

    StanderContext的生命周期 IOC容器的事件通讯机制 IOC容器的容器刷新机制

    Processed: 0.014, SQL: 9