揭秘Spring Boot的请求处理全流程:从启动到响应的奥秘

揭秘Spring Boot的请求处理全流程:从启动到响应的奥秘

前言

在 Spring Boot 中,一个简单的接口@RestController,就能轻松地实现复杂的Web服务。当我们在浏览器中访问http://localhost:8080/user/all,返回一个简单的字符串"all user",背后究竟发生了什么?

从Spring Boot启动时的自动配置,到内嵌的Servlet容器启动,再到DispatcherServlet的初始化,以及请求如何一步步被映射、执行,最终生成响应。

本文将以一个简单的示例接口为切入点,聊一聊Spring Boot从接收请求到生成响应的完整处理流程。

一、SprinngBoot启动阶段

1.1WebMvc自动配置

1.1.1自动配置类路径
1.1.2自动配置类注解
  • 类上注解

    1.  // SpringMVC的配置在DispatcherServlet、任务执行器、校验器等基础配置完成后加载,保证依赖关系
       @AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
       		ValidationAutoConfiguration.class })
      
    2.  // 条件注解,当前应用是基于Servlet的Web应用时,才会激活这个自动配置类
       @ConditionalOnWebApplication(type = Type.SERVLET)
      
    3.  // 条件注解,类路径下有Servlet, DispatcherServlet, WebMv***onfigurer时才激活这个自动配置类
       // Servlet是Servlet API的核心类,DispatcherServlet, WebMv***onfigurer是Spring MVC的核心 Servlet和扩展配置接口
       @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMv***onfigurer.class })
      
    4.  // 条件注解,容器中不存在WebMv***onfigurationSupport这个bean时,才激活这个自动配置类
       @ConditionalOnMissingBean(WebMv***onfigurationSupport.class)
      
    5.  // 确保WebMvcAutoConfiguration在绝大多数自动配置类之前加载,但仍为DispatcherServlet等基础配置留出更高的优先级。
       @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
      

    @AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
    ValidationAutoConfiguration.class })
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMv***onfigurer.class })
    @ConditionalOnMissingBean(WebMv***onfigurationSupport.class)
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
    public class WebMvcAutoConfiguration {
    // 省略部分代码…
    }

  • 自动配置类中静态内部类EnableWebMv***onfiguration

  • EnableWebMv***onfiguration继承了WebMv***onfigurationSupport,WebMv***onfigurationSupport中@Bean注解的bean也会处理

    @Configuration(proxyBeanMethods = false)
    @EnableConfigurationProperties(WebProperties.class)
    public static class EnableWebMv***onfiguration extends DelegatingWebMv***onfiguration implements ResourceLoaderAware {

    // 省略部分代码...
    
    @Bean
    @Override
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
            @Qualifier("mv***ontentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
            @Qualifier("mv***onversionService") FormattingConversionService conversionService,
            @Qualifier("mvcValidator") Validator validator) {
        RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(contentNegotiationManager,
                conversionService, validator);
        adapter.setIgnoreDefaultModelOnRedirect(
                this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect());
        return adapter;
    }
    
    // 省略部分代码...
    

    }

    // WebMv***onfigurationSupport
    public class WebMv***onfigurationSupport implements ApplicationContextAware, ServletContextAware {
    // 省略部分代码…

    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping(
    		@Qualifier("mv***ontentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
    		@Qualifier("mv***onversionService") FormattingConversionService conversionService,
    		@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
    
    	RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
    	mapping.setOrder(0);
    	mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
    	mapping.setContentNegotiationManager(contentNegotiationManager);
    	mapping.setCorsConfigurations(getCorsConfigurations());
    
    	PathMatchConfigurer pathConfig = getPathMatchConfigurer();
    	if (pathConfig.getPatternParser() != null) {
    		mapping.setPatternParser(pathConfig.getPatternParser());
    	} else {
    		mapping.setUrlPathHelper(pathConfig.getUrlPathHelperOrDefault());
    		mapping.setPathMatcher(pathConfig.getPathMatcherOrDefault());
    
    		Boolean useSuffixPatternMatch = pathConfig.isUseSuffixPatternMatch();
    		if (useSuffixPatternMatch != null) {
    			mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
    		}
    		Boolean useRegisteredSuffixPatternMatch = pathConfig.isUseRegisteredSuffixPatternMatch();
    		if (useRegisteredSuffixPatternMatch != null) {
    			mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
    		}
    	}
    	Boolean useTrailingSlashMatch = pathConfig.isUseTrailingSlashMatch();
    	if (useTrailingSlashMatch != null) {
    		mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
    	}
    	if (pathConfig.getPathPrefixes() != null) {
    		mapping.setPathPrefixes(pathConfig.getPathPrefixes());
    	}
    
    	return mapping;
    }
    
    // 省略部分代码...
    

    }

1.1.3RequestMappingHandlerAdapter适配器

详细职责

  • 适配控制器方法
    1. 不同类型的处理器(如控制器方法、返回值等)需要不同的适配逻辑。
    2. RequestMappingHandlerAdapter专门适配使用@RequestMapping标注的方法。
  • 参数解析
    1. 提供一组HandlerMethodArgumentResolver,解析控制器方法参数:
      • @RequestParam、@PathVariable注解的参数。
      • HTTP请求体(如JSON)解析成对象。
      • 当前的HttpServletRequest、HttpSession等内置参数。
  • 返回值处理
    1. 提供一组HandlerMethodReturnValueHandler,处理控制器方法的返回值:
      • 将对象序列化为JSON。
      • 返回View对象进行渲染。
  • 调用控制器方法
    1. 根据解析好的参数,执行控制器方法。
    2. 将返回值通过适配器处理并返回给客户端。

参数解析器及返回值解析器从哪儿来

  1.  // RequestMappingHandlerAdapter实现了InitializingBean。
     public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
     		implements BeanFactoryAware, InitializingBean {}
    
  2. 重写的afterPropertiesSet方法会在SpringBoot启动时,对实例requestMappingHandlerAdapter进行初始化阶段执行。

  3. afterPropertiesSet中添加了默认的参数解析器及返回值解析器

1.1.4RequestMappingHandlerMapping请求映射

详细职责

  • 扫描并注册映射关系
    1. 启动时扫描所有标注了@RequestMapping的控制器类和方法。
    2. 解析为映射信息(RequestMappingInfo),并存储到内部的数据结构中。
  • 匹配映射关系
    1. 当请求到达时,根据URL路径、HTTP方法等信息,从缓存中快速匹配对应的控制器方法(HandlerMethod)。

扫描及注册

  • RequestMappingHandlerMapping间接实现了InitializingBean,所以在RequestMappingHandlerMapping初始化时也会执行afterPropertiesSet方法。
  • afterPropertiesSet会调用父类AbstractHandlerMethodMapping的afterPropertiesSet方法
  • processCandidateBean方法会遍历候选bean,把带有@Controller或者@RequestMapping注解类中带有@RequestMapping注解的方法筛选出来。
  • 处理方法映射注册

1.2DispatcherServlet自动配置

1.2.1自动配置类路径
1.2.2自动配置类注解
  • 类上注解

    1.  // 优先级最高,最先处理该配置类
       @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
      
    2.  // 在ServletWebServerFactoryAutoConfiguration处理后进行自动配置处理
       @AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class)
      
    3.  // 条件注解,当前应用是基于Servlet的Web应用时,才会激活这个自动配置类
       @ConditionalOnWebApplication(type = Type.SERVLET)
      
    4.  // 类路径下有DispatcherServlet时才激活这个自动配置类
       @ConditionalOnClass(DispatcherServlet.class)
      

    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class)
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @ConditionalOnClass(DispatcherServlet.class)
    public class DispatcherServletAutoConfiguration {
    // 省略部分代码…
    }

内部静态配置类DispatcherServletConfiguration

  • 创建和配置DispatcherServlet实例。

    protected static class DispatcherServletConfiguration {
    @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
    DispatcherServlet dispatcherServlet = new DispatcherServlet();
    dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
    dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
    dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
    dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
    dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
    return dispatcherServlet;
    }
    }

内部静态配置类DispatcherServletRegistrationConfiguration

  • 注册一个DispatcherServlet的bean,设置初始配置,熟悉的loadOnStartup。Servlet启动时,servlet的启动顺序。

  • 这个阶段还在Spring容器中。

    protected static class DispatcherServletRegistrationConfiguration {

    @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
    @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
            WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
        DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
                webMvcProperties.getServlet().getPath());
        registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
        registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
        multipartConfig.ifAvailable(registration::setMultipartConfig);
        return registration;
    }
    

    }

  • 当tomcat容器(默认情况下)启动时,Servlet容器会调用所有ServletContextInitializer实现的onStartup方法。

  • onStartup方法

    // RegistrationBean
    public final void onStartup(ServletContext servletContext) throws ServletException {
    String description = getDescription();
    if (!isEnabled()) {
    logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
    return;
    }
    register(description, servletContext);
    }

  • 将DispatcherServlet注册到Servlet容器

    // ServletRegistrationBean
    protected ServletRegistration.Dynamic addRegistration(String description, ServletContext servletContext) {
    String name = getServletName();
    return servletContext.addServlet(name, this.servlet);
    }

二、接口访问阶段

2.1tomcat处理传入的请求

// StandardWrapperValve
public void invoke(Request request, Response response) throws IOException, ServletException {
	// servlet实例不可用时,分配一个servlet实例处理请求
    servlet = wrapper.allocate();
    
}
2.1.1初始化servlet
// StandardWrapper
public Servlet allocate() throws ServletException {
    
    initServlet(instance);
}


// HttpServletBean
public final void init() throws ServletException {
    // 省略部分代码...

    // 这里是留给子类(FrameworkServlet)做初始化的
    initServletBean();
}
  • 控制台日志开始的地方

web应用上下文已经在SpringBoot启动阶段创建,这里只是负责进行一些初始化工作

// FrameworkServlet
protected final void initServletBean() throws ServletException {
    getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
    if (logger.isInfoEnabled()) {
        logger.info("Initializing Servlet '" + getServletName() + "'");
    }
    long startTime = System.currentTimeMillis();

    try {
        this.webApplicationContext = initWebApplicationContext();
        initFrameworkServlet();
    }
    catch (ServletException | RuntimeException ex) {
        logger.error("Context initialization failed", ex);
        throw ex;
    }

    if (logger.isDebugEnabled()) {
        String value = this.enableLoggingRequestDetails ?
                "shown which may lead to unsafe logging of potentially sensitive data" :
                "masked to prevent unsafe logging of potentially sensitive data";
        logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +
                "': request parameters and headers will be " + value);
    }

    if (logger.isInfoEnabled()) {
        logger.info("***pleted initialization in " + (System.currentTimeMillis() - startTime) + " ms");
    }
}

protected WebApplicationContext initWebApplicationContext() {
    WebApplicationContext rootContext =
            WebApplicationContextUtils.getWebApplicationContext(getServletContext());
    WebApplicationContext wac = null;

    if (this.webApplicationContext != null) {
        // A context instance was injected at construction time -> use it
        wac = this.webApplicationContext;
        
        // 省略部分代码...
        
        ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
        
        // 省略部分代码...
    }
    // 省略部分代码...

    if (!this.refreshEventReceived) {
        // 手动触发刷新(做一些初始化工作)
        synchronized (this.onRefreshMonitor) {
            onRefresh(wac);
        }
    }

    if (this.publishContext) {
        // Publish the context as a servlet context attribute.
        String attrName = getServletContextAttributeName();
        getServletContext().setAttribute(attrName, wac);
    }

    return wac;
}
2.1.2干了哪些初始化工作
  • 初始化 MultipartResolver,用于处理文件上传

  • 初始化 LocaleResolver,用于处理国际化

  • 初始化 ThemeResolver,用于处理主题

  • 初始化 HandlerMappings,用于处理请求映射

  • 初始化 HandlerAdapters,用于处理请求适配

  • 初始化 HandlerExceptionResolvers,用于处理异常解析

  • 初始化 RequestToViewNameTranslator,用于将请求翻译为视图名称

  • 初始化 ViewResolvers,用于解析视图

  • 初始化 FlashMapManager,用于处理 Flash 映射

    // DispatcherServlet
    protected void onRefresh(ApplicationContext context) {
    initStrategies(context);
    }

    protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
    }

2.1.2.1初始化HandlerMappings
  • 查找ApplicationContext中的所有处理器映射(包括父容器的)

    private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;

    if (this.detectAllHandlerMappings) {
        Map<String, HandlerMapping> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList<>(matchingBeans.values());
            // We keep HandlerMappings in sorted order.
            AnnotationAwareOrder***parator.sort(this.handlerMappings);
        }
    }
    
    // 省略部分代码...
    
    // 如果没有找到其他映射,通过注册一个默认的HandlerMapping来确保至少有一个HandlerMapping。
    if (this.handlerMappings == null) {
        this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
        if (logger.isTraceEnabled()) {
            logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
                    "': using default strategies from DispatcherServlet.properties");
        }
    }
    // 如果至少有一个HandlerMapping使用了路径模式,解析请求路径的功能将被启用
    for (HandlerMapping mapping : this.handlerMappings) {
        if (mapping.usesPathPatterns()) {
            this.parseRequestPath = true;
            break;
        }
    }
    

    }

  • 所有的处理器映射

2.1.2.2初始化HandlerAdapters
  • 查找ApplicationContext中的所有处理器适配器(包括父容器的)

    private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;

    if (this.detectAllHandlerAdapters) {
        Map<String, HandlerAdapter> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerAdapters = new ArrayList<>(matchingBeans.values());
            AnnotationAwareOrder***parator.sort(this.handlerAdapters);
        }
    }
    
    // 省略部分代码...
    
    //如果没有找到其他适配器,通过注册默认的HandlerAdapters来确保至少有一些HandlerAdapters。
    if (this.handlerAdapters == null) {
        this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
        if (logger.isTraceEnabled()) {
            logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
                    "': using default strategies from DispatcherServlet.properties");
        }
    }
    

    }

2.1.3开始请求
// StandardWrapperValue
public void invoke(Request request, Response response) throws IOException, ServletException {
	filterChain.doFilter(request.getRequest(), response.getResponse());
}
2.1.3.1拦截器链调用
  • 如果有拦截器,先调用拦截器

  • 处理完拦截器,跳出拦截器连后,调用servlet实例(servlet的service方法)

    // ApplicationFilterChain
    private void internalDoFilter(ServletRequest request, ServletResponse response)
    throws IOException, ServletException {

    // 存在拦截器,则调用
    if (pos < n) {
        ApplicationFilterConfig filterConfig = filters[pos++];
        try {
            Filter filter = filterConfig.getFilter();
    
            if (request.isAsyncSupported() &&
                    "false".equalsIgnoreCase(filterConfig.getFilterDef().getAsyncSupported())) {
                request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
            }
            if (Globals.IS_SECURITY_ENABLED) {
                final ServletRequest req = request;
                final ServletResponse res = response;
                Principal principal = ((HttpServletRequest) req).getUserPrincipal();
    
                Object[] args = new Object[] { req, res, this };
                SecurityUtil.doAsPrivilege("doFilter", filter, classType, args, principal);
            } else {
                filter.doFilter(request, response, this);
            }
        } catch (IOException | ServletException | RuntimeException e) {
            throw e;
        } catch (Throwable e) {
            e = ExceptionUtils.unwrapInvocationTargetException(e);
            ExceptionUtils.handleThrowable(e);
            throw new ServletException(sm.getString("filterChain.filter"), e);
        }
        return;
    }
    
    // 跳出拦截器链,调用servlet实例
    try {
        if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
            lastServicedRequest.set(request);
            lastServicedResponse.set(response);
        }
    
        if (request.isAsyncSupported() && !servletSupportsAsync) {
            request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
        }
        if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse) &&
                Globals.IS_SECURITY_ENABLED) {
            final ServletRequest req = request;
            final ServletResponse res = response;
            Principal principal = ((HttpServletRequest) req).getUserPrincipal();
            Object[] args = new Object[] { req, res };
            SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args, principal);
        } else {
            // servlet的service方法
            servlet.service(request, response);
        }
    } catch (IOException | ServletException | RuntimeException e) {
        throw e;
    } catch (Throwable e) {
        e = ExceptionUtils.unwrapInvocationTargetException(e);
        ExceptionUtils.handleThrowable(e);
        throw new ServletException(sm.getString("filterChain.servlet"), e);
    } finally {
        if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
            lastServicedRequest.set(null);
            lastServicedResponse.set(null);
        }
    }
    

    }

  • servlet的service方法

    // FrameworkServlet
    protected void service(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
    processRequest(request, response);
    } else {
    super.service(request, response);
    }
    }

    protected final void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    processRequest(request, response);
    }

    protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    doService(request, response);
    

    }

2.1.3.2正式通过DispatcherServlet处理请求
// DispatcherServlet
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		logRequest(request);
    doDispatch(request, response);
}
  • 确定handler

  • 确定handler adapter

    // DispatcherServlet
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 省略部分代码…

    // 确定当前请求的处理器
    mappedHandler = getHandler(processedRequest);
    
    // 确定当前请求的处理器适配器
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    // 实际调用
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    // 省略部分代码...
    

    }

  • getHandler

  • getHandlerAdapter
  • handle

三、总结

3.1Spring Boot启动阶段的准备工作

3.1.1Web容器和DispatcherServlet的自动配置

Spring Boot 提供了许多自动配置类来简化开发,以下是与Web请求处理相关的重要类:

  • DispatcherServletAutoConfiguration:完成DispatcherServlet的注册和初始化。
  • WebMvcAutoConfiguration:为Spring MVC提供默认配置。
3.1.2DispatcherServlet 的注册
  • 在Spring Boot中,DispatcherServlet是Web应用的核心处理器,它的注册由DispatcherServletAutoConfiguration完成。
  • 默认注册的名称为dispatcherServlet
  • 映射路径为 /,拦截所有 HTTP 请求。
3.1.3WebMvc 配置

WebMvcAutoConfiguration会在没有用户自定义配置时,提供一套默认的Spring MVC配置,包括:

  • 注册RequestMappingHandlerMapping和RequestMappingHandlerAdapter。
  • 配置默认的视图解析器、静态资源处理器等。
3.1.4内嵌 Servlet 容器的启动

Spring Boot内置了Tomcat、Jetty等Servlet容器,以下是关键步骤:

  1. 内置容器启动:Spring Boot在启动时会通过EmbeddedWebServerFactory启动内置的Tomcat。
  2. Servlet注册:DispatcherServlet被注册为内置容器中的默认Servlet,用于接收和处理所有请求。

3.2请求到达Spring Boot的Servlet容器

3.2.1HTTP 请求进入Tomcat

当用户通过浏览器发送请求http://localhost:8080/user/all:

  1. 连接到Tomcat:
    Tomcat的Http11Processor会接收请求并解析为HTTP协议对象。
  2. 请求分发:
    请求被转发到DispatcherServlet,它是由Spring MVC注册的默认Servlet。

3.3DispatcherServlet的请求分发处理

3.1DispatcherServlet 的初始化

DispatcherServlet的init()方法会在第一次接收到请求时执行,它会完成以下准备工作:

  • 加载HandlerMapping(请求到处理器的映射)。
  • 加载HandlerAdapter(处理器的适配器)。
3.2核心组件的加载
  • RequestMappingHandlerMapping:扫描所有标注了@RequestMapping的方法,建立URL和处理器方法的映射关系。
  • RequestMappingHandlerAdapter:负责解析方法参数,调用控制器方法,并处理返回值。

3.4请求处理的完整流程

3.4.1URL到控制器方法的映射

DispatcherServlet调用RequestMappingHandlerMapping的getHandler()方法,根据请求的URL和HTTP方法匹配到对应的 HandlerMethod(这里对应 UserController#getAllUser 方法)。

3.4.2参数解析与方法调用

DispatcherServlet将请求传递给RequestMappingHandlerAdapter:

  • 解析控制器方法的参数,例如@RequestParam或JSON请求体等。
  • 调用控制器方法 getAllUser(),获得返回值"all user"。

3.5返回值处理

3.5.1处理返回值
  • 返回值通过 HandlerMethodReturnValueHandler 处理:
    • 如果是字符串(如 "all user"),则直接写入到 HTTP 响应中。

3.6最终生成响应

DispatcherServlet 将处理结果封装为 HTTP 响应,并交给 Tomcat。
Tomcat 将响应返回给客户端,最终浏览器显示 "all user"

转载请说明出处内容投诉
CSS教程网 » 揭秘Spring Boot的请求处理全流程:从启动到响应的奥秘

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买