当前位置: 首页 > article >正文

SpringMVC源码-AbstractUrlHandlerMapping处理器映射器将实现Controller接口的方式定义的路径存储进去

DispatcherServlet的initStrategies方法用来初始化SpringMVC的九大内置组件
initStrategies

	protected void initStrategies(ApplicationContext context) {
		// 初始化 MultipartResolver:主要用来处理文件上传.如果定义过当前类型的bean对象,那么直接获取,如果没有的话,可以为null
		initMultipartResolver(context);
		// 初始化 LocaleResolver:主要用来处理国际化配置,基于URL参数的配置(AcceptHeaderLocaleResolver),基于session的配置(SessionLocaleResolver),基于cookie的配置(CookieLocaleResolver)
		initLocaleResolver(context);
		// 初始化 ThemeResolver:主要用来设置主题Theme
		initThemeResolver(context);
		// 初始化 HandlerMapping:映射器,用来将对应的request跟controller进行对应
		initHandlerMappings(context);
		// 初始化 HandlerAdapter:处理适配器,主要包含Http请求处理器适配器,简单控制器处理器适配器,注解方法处理器适配器
		initHandlerAdapters(context);
		// 初始化 HandlerExceptionResolver:基于HandlerExceptionResolver接口的异常处理
		initHandlerExceptionResolvers(context);
		// 初始化 RequestToViewNameTranslator:当controller处理器方法没有返回一个View对象或逻辑视图名称,并且在该方法中没有直接往response的输出流里面写数据的时候,spring将会采用约定好的方式提供一个逻辑视图名称
		initRequestToViewNameTranslator(context);
		// 初始化 ViewResolver: 将ModelAndView选择合适的视图进行渲染的处理器
		initViewResolvers(context);
		// 初始化 FlashMapManager: 提供请求存储属性,可供其他请求使用
		initFlashMapManager(context);
	}

initHandlerMappings初始化 HandlerMapping:映射器,用来将对应的request跟controller进行对应,该方法是在构造SpringMVC容器调用的。
调用链路如下:

ApplicationObjectSupport实现了ApplicationContextAware接口,所以会调用setApplicationContext:78, ApplicationObjectSupport (org.springframework.context.support)
invokeAwareInterfaces:146, ApplicationContextAwareProcessor (org.springframework.context.support)
postProcessBeforeInitialization:118, ApplicationContextAwareProcessor (org.springframework.context.support)
applyBeanPostProcessorsBeforeInitialization:497, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
完成实例化、属性填充之后进行初始化调用bpp的方法——initializeBean:2256, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:736, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:630, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:361, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createDefaultStrategy:957, DispatcherServlet (org.springframework.web.servlet)
获得默认配置的handlerMapping类——getDefaultStrategies:925, DispatcherServlet (org.springframework.web.servlet)
initHandlerMappings:657, DispatcherServlet (org.springframework.web.servlet)
initStrategies:529, DispatcherServlet (org.springframework.web.servlet)
onRefresh:514, DispatcherServlet (org.springframework.web.servlet)
onApplicationEvent:901, FrameworkServlet (org.springframework.web.servlet)
onApplicationEvent:1277, FrameworkServlet$ContextRefreshListener (org.springframework.web.servlet)
onApplicationEvent:1273, FrameworkServlet$ContextRefreshListener (org.springframework.web.servlet)
onApplicationEvent:64, GenericApplicationListenerAdapter (org.springframework.context.event)
onApplicationEventInternal:109, SourceFilteringListener (org.springframework.context.event)
onApplicationEvent:73, SourceFilteringListener (org.springframework.context.event)
doInvokeListener:215, SimpleApplicationEventMulticaster (org.springframework.context.event)
invokeListener:202, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:164, SimpleApplicationEventMulticaster (org.springframework.context.event)
publishEvent:440, AbstractApplicationContext (org.springframework.context.support)
publishEvent:379, AbstractApplicationContext (org.springframework.context.support)
finishRefresh:1053, AbstractApplicationContext (org.springframework.context.support)
refresh:618, AbstractApplicationContext (org.springframework.context.support)
configureAndRefreshWebApplicationContext:759, FrameworkServlet (org.springframework.web.servlet)
createWebApplicationContext:715, FrameworkServlet (org.springframework.web.servlet)
createWebApplicationContext:773, FrameworkServlet (org.springframework.web.servlet)
initWebApplicationContext:625, FrameworkServlet (org.springframework.web.servlet)
initServletBean:536, FrameworkServlet (org.springframework.web.servlet)
init:185, HttpServletBean (org.springframework.web.servlet)
init:158, GenericServlet (javax.servlet)
initServlet:1164, StandardWrapper (org.apache.catalina.core)
loadServlet:1117, StandardWrapper (org.apache.catalina.core)
load:1010, StandardWrapper (org.apache.catalina.core)
loadOnStartup:4957, StandardContext (org.apache.catalina.core)
startInternal:5264, StandardContext (org.apache.catalina.core)
start:183, LifecycleBase (org.apache.catalina.util)
addChildInternal:726, ContainerBase (org.apache.catalina.core)
addChild:698, ContainerBase (org.apache.catalina.core)
addChild:696, StandardHost (org.apache.catalina.core)
manageApp:1783, HostConfig (org.apache.catalina.startup)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:293, BaseModelMBean (org.apache.tomcat.util.modeler)
invoke:819, DefaultMBeanServerInterceptor (com.sun.jmx.interceptor)
invoke:801, JmxMBeanServer (com.sun.jmx.mbeanserver)
createStandardContext:460, MBeanFactory (org.apache.catalina.mbeans)
createStandardContext:408, MBeanFactory (org.apache.catalina.mbeans)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:293, BaseModelMBean (org.apache.tomcat.util.modeler)
invoke:819, DefaultMBeanServerInterceptor (com.sun.jmx.interceptor)
invoke:801, JmxMBeanServer (com.sun.jmx.mbeanserver)
invoke:468, MBeanServerAccessController (com.sun.jmx.remote.security)
doOperation:1468, RMIConnectionImpl (javax.management.remote.rmi)
access$300:76, RMIConnectionImpl (javax.management.remote.rmi)
run:1309, RMIConnectionImpl$PrivilegedOperation (javax.management.remote.rmi)
doPrivileged:-1, AccessController (java.security)
doPrivilegedOperation:1408, RMIConnectionImpl (javax.management.remote.rmi)
invoke:829, RMIConnectionImpl (javax.management.remote.rmi)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
dispatch:346, UnicastServerRef (sun.rmi.server)
run:200, Transport$1 (sun.rmi.transport)
run:197, Transport$1 (sun.rmi.transport)
doPrivileged:-1, AccessController (java.security)
serviceCall:196, Transport (sun.rmi.transport)
handleMessages:568, TCPTransport (sun.rmi.transport.tcp)
run0:826, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
lambda$run$0:683, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
run:-1, 1637217430 (sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$26)
doPrivileged:-1, AccessController (java.security)
run:682, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
runWorker:1142, ThreadPoolExecutor (java.util.concurrent)
run:617, ThreadPoolExecutor$Worker (java.util.concurrent)
run:748, Thread (java.lang)

ApplicationObjectSupport等相关类继承关系
在这里插入图片描述
ApplicationObjectSupport实现了ApplicationContextAware接口,setApplicationContext方法里调用initApplicationContext(context);
在这里插入图片描述
经这一步一直调用到:
AbstractHandlerMapping的initApplicationContext方法:

	/**初始化拦截器
	 * Initializes the interceptors.
	 * @see #extendInterceptors(java.util.List)
	 * @see #initInterceptors()
	 */
	@Override
	protected void initApplicationContext() throws BeansException {
		// 空实现,交给子类实现,用于注册自定义的拦截器到interceptors中,目前暂无子类实现
		extendInterceptors(this.interceptors);
		// 扫描已注册的MappedInterceptor的Bean们,添加到adaptedInterceptors中
		detectMappedInterceptors(this.adaptedInterceptors);
		// 将interceptors初始化成 HandlerInterceptor类型,添加到adaptedInterceptors中
		initInterceptors();
	}

detectMappedInterceptors执行:
在这里插入图片描述
SpringMVC的配置文件applicationContext.xml有定义拦截器:

    <mvc:interceptors>
    <bean class="com.mashibing.interceptor.HandlerMappingInterceptor"/>
    </mvc:interceptors>

将配置文件中配置的拦截器生成放在mappedInterceptors中。
initInterceptors执行,interceptors为空,跳过执行。


	/**
	 * 初始化interceptors,并适配HandlerInterceptors和WebRequestInterceptor
	 *
	 * Initialize the specified interceptors adapting
	 * {@link WebRequestInterceptor}s to {@link HandlerInterceptor}.
	 * @see #setInterceptors
	 * @see #adaptInterceptor
	 */
	protected void initInterceptors() {
		if (!this.interceptors.isEmpty()) {
			for (int i = 0; i < this.interceptors.size(); i++) {
				Object interceptor = this.interceptors.get(i);
				if (interceptor == null) {
					throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
				}
				// 将interceptors初始化成HandlerInterceptor类型,添加到adaptedInterceptors中
				// 注意,HandlerInterceptor无需进行路径匹配,直接拦截全部
				this.adaptedInterceptors.add(adaptInterceptor(interceptor));
			}
		}
	}

AbstractDetectingUrlHandlerMapping的initApplicationContext中方法detectHandlers开始执行:
AbstractDetectingUrlHandlerMapping类的detectHandlers方法开始执行:


	/**
	 * 根据配置的detectHandlersInAncestorContexts参数从springmvc容器或者父容器中找到所有bean的beanName,然后使用determineUrlsForHandler方法
	 * 对每个beanName解析出对应的urls,如果解析结果不为空,则解析出urls和beanName注册到父类的map中,
	 *
	 * Register all handlers found in the current ApplicationContext.
	 * <p>The actual URL determination for a handler is up to the concrete
	 * {@link #determineUrlsForHandler(String)} implementation. A bean for
	 * which no such URLs could be determined is simply not considered a handler.
	 * @throws org.springframework.beans.BeansException if the handler couldn't be registered
	 * @see #determineUrlsForHandler(String)
	 */
	protected void detectHandlers() throws BeansException {
		// 从spring上下文获取所有Object类型的bean名称
		ApplicationContext applicationContext = obtainApplicationContext();//获取的是springmvc的容器
		// 获取容器中所有bean的名字
		String[] beanNames = (this.detectHandlersInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
				applicationContext.getBeanNamesForType(Object.class));

		// Take any bean name that we can determine URLs for.
		// 对每一个beanName解析url,如果能解析到就注册到父类的map中
		for (String beanName : beanNames) {
			// 使用beanName解析url,模板方法,有子类实现 检查给定bean的名称和别名,查找以“”开头的url。
			String[] urls = determineUrlsForHandler(beanName);
			// 如果该bean存在对应的url,则添加该处理器
			if (!ObjectUtils.isEmpty(urls)) {
				// URL paths found: Let's consider it a handler.
				// 调用父类的方法,往handlerMap中添加注册器
				registerHandler(urls, beanName);
			}
		}

		if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) {
			logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName());
		}
	}
	

beanNames 是SpringMVC容器的所有对象的名称:使用beanName解析url,模板方法,有子类实现 检查给定bean的名称和别名,查找以“/”开头的url。调用父类的方法,往handlerMap中添加注册器
applicationContext.xml文件定义的bean是以/开头的,会被放到handlerMap

    <bean name="/test01" class="com.mashibing.controller.testController.Test01"></bean>
    <bean id="/test02" class="com.mashibing.controller.testController.Test02"></bean>

在这里插入图片描述
在这里插入图片描述
最终放到AbstractUrlHandlerMapping的handlerMap中


http://www.kler.cn/a/327085.html

相关文章:

  • 商品信息的修改、删除功能
  • 二、应用层,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》
  • C++ 编程基础(4)函数 | 4.1、函数概述
  • 抓住亚马逊、shein新品扶持期,利用测评提升搜索排名与销量
  • 25国考照片处理器使用流程图解❗
  • 【温酒笔记】UART
  • 健康生活,从日常细节开始
  • NVLM多模态 LLM 在图像和语言任务中的表现优于 GPT-4o
  • Oracle数据恢复—异常断电导致Oracle数据库报错的数据恢复案例
  • 第167天:应急响应-日志自动提取分析项目_ELK_Logkit_LogonTracer_Anolog等
  • Mysql高级篇(下)——日志
  • Microsoft Edge 五个好用的插件
  • MySQL存储过程循环操作
  • LVGL 笔记
  • SpringBoot3+Swagger3(最新版springdoc-openapi教程)
  • 组合优化与凸优化 学习笔记5 对偶拉格朗日函数
  • 21 vue3之发布npm插件(hook自定义指令)
  • 国产RISC-V案例分享,基于全志T113-i异构多核平台!
  • 【刷题6】一维前缀和、二维前缀和
  • 学习VTK的目的和方法
  • 速盾:cdn加速什么好?
  • 【Linux探索学习】第二弹——Linux的基础指令(中)——夯实基础第二篇
  • 25考研咨询周开启,西安电子科技大学是否改考408??
  • HarmonyOS Next系列之水波纹动画特效实现(十三)
  • ClickHouse入库时间与实际相差8小时问题
  • 升级FreeBSD13.2到14.1-RELEASE