假设我有一个用 @Controller 注释的类以及实例方法的相应映射,如下所示。
@Controller
@ResponseBody
public class UserController {
@GetMapping("/example")
public User fetchUserExample() {
// ...
}
}
另外,假设有 1000 个像上面这样具有不同 URL 映射的 Controller 。 我调用了任意 URL 和相应的 Controller ,并调用相应的方法并返回响应。
但我感到困惑的是,dispatcherServlet 到底如何知道在哪里可以找到所请求 URL 的方法?它是否会一一扫描每个 Controller 类以查找匹配项,并且是否对每个请求都执行此操作?如果是这样,这似乎并不是一个有效的方法。
我知道我们也可以对类进行注释,但这仍然不能回答问题,因为它仍然需要扫描类以进行匹配。
我希望它能够对 Controller 及其各自的映射进行某种跟踪。
我为此在 google 上搜索了很多,但几乎无论我走到哪里,都只浏览了表面,例如 @GetMapping、@RequestMapping
等注释告诉它要调用的方法。但我们知道这一点。 DispatcherServlet 首先如何精确定位该类,还是遵循我上面编写的方法?
一些网站提到了诸如 HandlerMapping、SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter 之类的东西,但由于我是 Spring 新手,这些东西对我来说不明白它们是如何出现在此处的。
如有任何意见,我们将不胜感激。
最佳答案
由于映射注释是静态的,并且在运行时不会更改,因此每次处理请求时都不需要扫描每个 Controller 类来查找匹配的方法。只需在应用程序启动时扫描一次并将扫描结果存储到一种 map 中即可。因此,找到请求调用哪个方法只需从该映射中查找一些数据,这应该非常有效。
如果您对实际代码感兴趣,请查看RequestMappingHandlerMapping#lookupHandlerMethod()
用于查找为请求调用哪个方法的逻辑。扫描结果存储到内部 MappingRegistry
中,lookupHandlerMethod()
将从中获取数据以查找匹配的方法。
您还可以尝试获取 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 请求映射到哪个处理程序方法。
关于spring - DispatcherServlet 如何准确地确定要调用哪个 Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59179214/