SpringBoot源码系列(4):请求映射

布鸽不鸽 Lv4

前言

在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的源码中,我们可以看到,doGetdoPostdoPutdoDelete等底层都是调用的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 {

// 决定当前请求的handler
processedRequest = checkMultipart(request);
mappedHandler = getHandler(processedRequest);

if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}

// 这里使用了适配器模式,拿到了HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// 处理后返回ModelAndView
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
/*
代码有删减
映射了所有标@RequestMapping注解的Controller的路径
*/
@Override
protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
RequestMappingHandlerMapping mapping = this.mvcRegistrations.getRequestMappingHandlerMapping();
}

/*
代码有删减
欢迎页
*/
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {

}
  • 标题: SpringBoot源码系列(4):请求映射
  • 作者: 布鸽不鸽
  • 创建于 : 2023-05-07 15:27:14
  • 更新于 : 2023-06-26 09:30:36
  • 链接: https://xuedongyun.cn//post/15349/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论