Issue
Let's say I have a class annotated with @Controller and the respective mappings for the instance method like this.
@Controller
@ResponseBody
public class UserController {
@GetMapping("/example")
public User fetchUserExample() {
// ...
}
}
Also, let's say there are a 1000 controllers like above with different URL mappings. I invoked say any of the URL and the respective controller is found and the respective method is called and response is returned.
But what I am confused about is how exactly dispatcherServlet knows where it'd find the method for the requested URL? Does it scans through each and every controller classes one by one looking for a match and does it do this for every request? If so, it doesn't really seem to be an effective approach.
I know we can annotate the class as well but that still doesn't answer the question as it'd still need to scan the classes for a match.
I was hoping it'd be maintaining some kind of track about the controllers and their respective mappings.
I googled a lot for this but almost wherever I went only skimmed through the surface that the annotations such as @GetMapping, @RequestMapping
tell it about the method to call. But we know that. How does dispatcherServlet pinpoints the class in the first place or does it follow the approach that I wrote above?
Some sites mentioned things like HandlerMapping, SimpleControllerHandlerAdapter, RequestMappingHandlerAdapter
but since I am new to Spring these things don't make sense to me as to how they come in picture here.
Any input would be appreciated.
Solution
As the mapping annotations are static and never be changed during runtimes, it does not need to scan every controller class to find the matched method whenever it process a request. Just scan it once at the application start and store the scanning result to a kind of map . So finding which method to be invoked for a request is just a matter of looking up some data from this map which should be very effective.
If you are interested in the actual codes , look at RequestMappingHandlerMapping#lookupHandlerMethod()
for the logic of finding which method to be invoked for a request. The scanning results are stored to an internal MappingRegistry
which lookupHandlerMethod()
will get the data from it for finding the matched method.
You can also try to grab a RequestMappingHandlerMapping
bean , get the mapping of MappingRegistry
by :
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("-----");
});
which will print out which URL request is mapped to which handler method.
Answered By - Ken Chan
Answer Checked By - Willingham (JavaFixing Volunteer)