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

前言

在SpringBoot/SpringMVC中,请求映射是一个很重要的概念。众所周知,应用中实际上只有一个DispatcherServlet处理所有请求,再交由对应的处理器来处理。本文中SpringBoot版本号为2.7.5。

原文地址:https://xuedongyun.cn/post/15349/

请求映射原理

FrameworkServlet

我们知道在SpringMVC中,所有的请求都交由DispatcherServlet统一处理。首先我们看看DispatcherServlet的继承结构

HttpServlet
    HttpServletBean
        FrameworkServlet
            DispatcherServlet

FrameworkServlet的源码中,我们可以看到,doGetdoPostdoPutdoDelete等底层都是调用的processRequest方法

@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    processRequest(request, response);
}

processRequest方法核心在于调用了doService方法

// 代码有删减
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
    try {
        doService(request, response);
    }
}

DispatcherServlet

FrameworkServlet并未实现doService方法,但是DispatcherServlet继承了该类,实现了此方法。doService方法核心在于调用了doDispatch方法

// 代码有删减
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    try {
        doDispatch(request, response);
    }
}

doDispatch方法中,会根据请求,找到哪个handler(controller)能处理当前请求。随后使用找到的handler处理请求,获得ModelAndView

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,我们查看其源码

@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,调试可以看到,包含五个

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

/*
	代码有删减
	映射了所有标@RequestMapping注解的Controller的路径
*/
@Override
protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
    RequestMappingHandlerMapping mapping = this.mvcRegistrations.getRequestMappingHandlerMapping();
}

/*
	代码有删减
	欢迎页
*/
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
        FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值