controller路径解析原理

  • 背景
  • 前期准备
  • 创建项目
  • 查看源码
  • MappingRegistry

背景

有一次面试,面试官问我同一个controller里面路径能不能重复,我斩钉截铁的回答不行,然后问我原因的时候我也不知道,最后面试官微微一笑然后就让我回去等通知了。
最近突然想到这个问题,然后就看了一下源码,在此记录一下

前期准备

我们都知道,如果在同一个controller定义两个一样的请求路径在启动的时候会报错,查询报错提示语所在类就能一步一步查看原因。

创建项目

先创建一个springboot项目,再创建一个controller

TestController.java

@RestController
@RequestMapping("test")
public class TestController {

    @GetMapping("/test2")
    public String test1(){
        return "test1=";
    }

    @GetMapping("/test2")
    public String test2(){
        return "test2=";
    }
}

启动的时候报错,这是因为路径相同了

java如果处理两个请求同时进只拦截一个的逻辑处理 两个controller的请求路径相同_查看源码

查看源码

通过查询报错信息找到了报错所在类的方法:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#assertUniqueMethodMapping

java如果处理两个请求同时进只拦截一个的逻辑处理 两个controller的请求路径相同_spring_02


这个方法的作用是每次把路径映射进来的时候都会检查一下路径是不是重复的,如果重复就抛异常。

MappingRegistry

MappingRegistry 是AbstractHandlerMethodMapping的一个内部类,

官方注释是这样的:

java如果处理两个请求同时进只拦截一个的逻辑处理 两个controller的请求路径相同_spring_03


大概意思就是这个类的作用是维护映射的一个注册表并提供并发访问。

在MappingRegistry里面维护着一个Map<T, MappingRegistration> registry 注册表,还维护一个Map<T, HandlerMethod> mappingLookup,这个mappingLookup存放着所有的映射和方法处理器,并不是线程安全的,MappingRegistry 有个register方法,每次有映射注册的时候首先就是检查路径是否重复,重复就抛异常,然后就是向mappingLookup put进去一条数据进去,同时解析后的数据放到registry 注册表中。

这只是写了一个很简单的URL注入过程,这是针对这个问题的,背后还有很多逻辑就不在这里一一赘述了,以后会再写几篇文章说明的。

能力一般,水平有限,如有问题,请多指出。