前言
在SpringBoot/SpringMVC中,请求映射是一个很重要的概念。众所周知,应用中实际上只有一个DispatcherServlet处理所有请求,再交由对应的处理器来处理。本文中SpringBoot版本号为2.7.5。
原文地址:https://xuedongyun.cn/post/15349/
请求映射原理
FrameworkServlet
我们知道在SpringMVC中,所有的请求都交由DispatcherServlet
统一处理。首先我们看看DispatcherServlet
的继承结构
1 2 3 4
| HttpServlet HttpServletBean FrameworkServlet DispatcherServlet
|
在FrameworkServlet
的源码中,我们可以看到,doGet
,doPost
,doPut
,doDelete
等底层都是调用的processRequest
方法
1 2 3 4 5 6
| @Override protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response); }
|
processRequest
方法核心在于调用了doService
方法
1 2 3 4 5 6 7
| protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { doService(request, response); } }
|
DispatcherServlet
FrameworkServlet
并未实现doService
方法,但是DispatcherServlet
继承了该类,实现了此方法。doService
方法核心在于调用了doDispatch
方法
1 2 3 4 5 6 7
| @Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { try { doDispatch(request, response); } }
|
doDispatch
方法中,会根据请求,找到哪个handler(controller)能处理当前请求。随后使用找到的handler处理请求,获得ModelAndView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { processedRequest = checkMultipart(request); mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); }
|
可以看到,最为关键的方法为getHandler
方法,确定请求具体的handler,我们查看其源码
1 2 3 4 5 6 7 8 9 10 11 12
| @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
,调试可以看到,包含五个
1 2 3 4 5 6
| this.handlerMappings = {ArrayList} size = 5 0 = {RequestMappingHandlerMapping} 1 = {WelcomePageHandlerMapping} 2 = {BeanNameUrlHandlerMapping} 3 = {RouterFunctionMapping} 4 = {SimpleUrlHandlerMapping}
|
RequestMappingHandlerMapping
保存了所有@RequestMapping
注解的请求映射规则。在.mappingRegistry.registry
可以看到所有Controller
路径都在其中(以及错误路径/error)
WebMvcAutoConfiguration
在WebMvcAutoConfiguration
中,SpringBoot为我们注册了所有的HandlerMapping
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
@Override protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() { RequestMappingHandlerMapping mapping = this.mvcRegistrations.getRequestMappingHandlerMapping(); }
@Bean public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) { }
|