【问题标题】:How does DispatcherServlet exactly figures out which controller to call?DispatcherServlet 如何准确地确定要调用哪个控制器?
【发布时间】:2020-03-29 10:39:59
【问题描述】:

假设我有一个用 @Controller 注释的类,以及像这样的实例方法的相应映射。

@Controller
@ResponseBody
public class UserController {

    @GetMapping("/example")
    public User fetchUserExample() {
        // ...
    }
}

另外,假设有 1000 个像上面这样具有不同 URL 映射的控制器。 我调用说任何 URL 和相应的控制器被找到,相应的方法被调用并返回响应。

但我感到困惑的是,dispatcherServlet 究竟是如何知道它在哪里可以找到请求的 URL 的方法的?它是否会逐个扫描每个控制器类以寻找匹配项,并且是否对每个请求都执行此操作?如果是这样,这似乎不是一个有效的方法。

我知道我们也可以注释类,但这仍然不能回答问题,因为它仍然需要扫描类以查找匹配项。

我希望它能保持某种关于控制器及其各自映射的跟踪。

我为此搜索了很多,但几乎无论我走到哪里,都只浏览了@GetMapping, @RequestMapping 等注释告诉它要调用的方法的表面。但我们知道。 dispatcherServlet 是如何首先确定类的还是遵循我上面写的方法?

有些网站提到了 HandlerMapping, SimpleControllerHandlerAdapter, RequestMappingHandlerAdapter 之类的东西,但由于我是 Spring 新手,所以这些东西对我来说没有意义,它们是如何出现在这里的。

我们将不胜感激。

【问题讨论】:

    标签: spring servlets model-view-controller dispatcher


    【解决方案1】:

    由于映射注解是静态的,并且在运行时永远不会更改,因此它不需要在处理请求时扫描每个控制器类以找到匹配的方法。只需在应用程序启动时扫描一次并将扫描结果存储到一种地图中。所以找到一个请求调用哪个方法只是从这个映射中查找一些数据的问题,这应该是非常有效的。

    如果您对实际代码感兴趣,请查看RequestMappingHandlerMapping#lookupHandlerMethod(),了解查找要为请求调用哪个方法的逻辑。扫描结果存储到内部MappingRegistrylookupHandlerMethod() 会从中获取数据以找到匹配的方法。

    你也可以尝试抓取一个RequestMappingHandlerMapping bean,通过以下方式获取MappingRegistry的映射:

    RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
    Map<RequestMappingInfo, HandlerMethod> handlerMethodMapping = mapping.getHandlerMethods();
    handlerMethodMapping.forEach((k,v)->{
        System.out.println(k);
        System.out.println(v);
        System.out.println("-----");
    });
    

    这将打印出哪个 URL 请求映射到哪个处理程序方法。

    【讨论】:

    • 谢谢。正是我需要知道的。
    猜你喜欢
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多