Spring源码解析 -- SpringWeb请求映射Map初始化

本文深入解析SpringWeb请求映射的初始化过程,从DispatcherServlet的handlerMappings入手,逐步揭示RequestMappingHandlerMapping如何完成请求路径与处理方法的映射。文章通过源码分析,展示了MappingRegistry关键代码,探讨了应用启动、初始化和请求映射的流程。
摘要由CSDN通过智能技术生成

简介

在上篇文章中,大致解析了Spring如何将请求路径与处理方法进行映射,但映射相关的初始化对于我们来说还是一团迷雾

本篇文章就来探索下,请求路径和处理方法的映射,是如何进行初始化的

概览

基于上篇文章:Spring 源码解析 – SpringWeb请求映射解析

本篇文章本来想早点写完,但一直卡着,没有找到想要的切入点,还好在周四左右定位到了相关的关键代码,初步探索到相关初始化的代码过程

接下来就展示这段时间的定位和解析过程,下面是自己这段时间探索历程:

  • 想定位 handlerMappings 的初始化,但没有定位请求URL和处理方法相关初始化的东西
  • 回过来头来看 handlerMappings ,看其有哪些东西,发现这个Map中并没有自定义的HelloWorld
  • 意识到关键的 RequestMappingHandlerMapping,跟踪发送只有在这个类型才成功匹配
  • 回顾上篇的请求映射解析,在 RequestMappingHandlerMapping 细致初始化相关的代码
  • 成功找到相关的路径和处理方法初始化的关键代码

接下来详细看下:

源码解析

初步探索初始化:误入歧途

在类: DispatcherServlet.java 中,我们定位到 mappedHandler 获取的关键代码

@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   
    if (this.handlerMappings != null) {
   
	for (HandlerMapping mapping : this.handlerMappings) {
   
		HandlerExecutionChain handler = mapping.getHandler(request);
		if (handler != null) {
   
			return handler;
		}
	}
    }
	return null;
}

它就是遍历了: handlerMappings ,于是去跟踪了 handlerMappings 初始化过程

结果失败而归,没有找到自己想要的东西,并没有发现自定义类: HelloWorld 的相关东西

这块有很多的代码,里面也有很多的东西,但在这里就不展示出来了,感兴趣的老哥可自行探索

回顾请求映射查找匹配:幡然醒悟

探索 handlerMappings 无果,于是回到上面那段遍历处理

经过调试 handlerMappings 基本是固定的,包含下面的类:

  • this.handlerMappings
    • RequestMappingHandlerMapping
    • BeanNameUrlHandlerMapping
    • RouterFunctionMapping
    • SimpleUrlHandlerMapping
    • WelcomePageHandlerMapping

而匹配的成功的是: RequestMappingHandlerMapping ,其返回了我们想要的处理方法 HelloWorld

调试中很疑惑为啥初期要初始化这几个了,并且再套了一层请求匹配,目前掌握的知识还不足于破解,只能后面再探索了

于是开始梳理 RequestMappingHandlerMapping 的请求匹配,在下面的一段关键代码匹配成功了:

    # AbstractHandlerMethodMapping.java
    @Nullable
	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
   
		List<Match> matches = new ArrayList<>();
        // 在这里拿到了匹配结果
		List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
		if (directPathMatches != null) {
   
			addMatchingMappings(directPathMatches, matches, request);
		}
		if (matches.isEmpty()) {
   
			addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
		}
		.......
	}

在上面的代码中就匹配成功了,其中匹配的方法很简单粗暴:

    # AbstractHandlerMethodMapping.java -- MappingRegistry
    @Nullable
	public List<T> getMappingsByDirectPath(String urlPath) {
   
		return this.pathLookup.get(urlPath);
	}

于是关键点到了 this.mappingRegistry 的初始化,找到初始化的代码,打上断点

期间以为是在类:AbstractHandlerMethodMapping 中进行的初始的,在下面的函数打上了断点:

    # AbstractHandlerMethodMapping.java
    public void setPatternParser(PathPatternParser patternParser) {
   
		Assert.state(this.mappingRegistry.getRegistrations().isEmpty(),
				"PathPatternParser must be set before the initialization of " +
						"request mappings through InitializingBean#afterPropertiesSet.");
		super.setPatternParser(patternParser);
	}

    public void registerMapping(T mapping, Object handler, Method method) {
   
		if (logger.isTraceEnabled()) {
   
			logger.trace("Register \"" + mapping + "\" to " + method.toGenericString());
		}
		this.mappingRe
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值