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

645 阅读10分钟

前言

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

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

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

一、SprinngBoot启动阶段

1.1WebMvc自动配置

1.1.1自动配置类路径

image-20241121194236998

1.1.2自动配置类注解

  • 类上注解

    1.   // SpringMVC的配置在DispatcherServlet、任务执行器、校验器等基础配置完成后加载,保证依赖关系
        @AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
                ValidationAutoConfiguration.class })
      
    2.   // 条件注解,当前应用是基于Servlet的Web应用时,才会激活这个自动配置类
        @ConditionalOnWebApplication(type = Type.SERVLET)
      
    3.   // 条件注解,类路径下有Servlet, DispatcherServlet, WebMvcConfigurer时才激活这个自动配置类
        // Servlet是Servlet API的核心类,DispatcherServlet, WebMvcConfigurer是Spring MVC的核心 Servlet和扩展配置接口
        @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
      
    4.   // 条件注解,容器中不存在WebMvcConfigurationSupport这个bean时,才激活这个自动配置类
        @ConditionalOnMissingBean(WebMvcConfigurationSupport.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, WebMvcConfigurer.class })
 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
 public class WebMvcAutoConfiguration {
     // 省略部分代码...
 }
 ​
  • 自动配置类中静态内部类EnableWebMvcConfiguration
  • EnableWebMvcConfiguration继承了WebMvcConfigurationSupport,WebMvcConfigurationSupport中@Bean注解的bean也会处理
 @Configuration(proxyBeanMethods = false)
 @EnableConfigurationProperties(WebProperties.class)
 public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
 ​
     // 省略部分代码...
 ​
     @Bean
     @Override
     public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
             @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
             @Qualifier("mvcConversionService") FormattingConversionService conversionService,
             @Qualifier("mvcValidator") Validator validator) {
         RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(contentNegotiationManager,
                 conversionService, validator);
         adapter.setIgnoreDefaultModelOnRedirect(
                 this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect());
         return adapter;
     }
 ​
     // 省略部分代码...
 }
 // WebMvcConfigurationSupport
 public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
     // 省略部分代码...
     
     @Bean
     public RequestMappingHandlerMapping requestMappingHandlerMapping(
             @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
             @Qualifier("mvcConversionService") 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中添加了默认的参数解析器及返回值解析器

image-20241122153546994

1.1.4RequestMappingHandlerMapping请求映射

详细职责

  • 扫描并注册映射关系

    1. 启动时扫描所有标注了@RequestMapping的控制器类和方法。
    2. 解析为映射信息(RequestMappingInfo),并存储到内部的数据结构中。
  • 匹配映射关系

    1. 当请求到达时,根据URL路径、HTTP方法等信息,从缓存中快速匹配对应的控制器方法(HandlerMethod)。

扫描及注册

  • RequestMappingHandlerMapping间接实现了InitializingBean,所以在RequestMappingHandlerMapping初始化时也会执行afterPropertiesSet方法。

image-20241122154827805

  • afterPropertiesSet会调用父类AbstractHandlerMethodMapping的afterPropertiesSet方法

image-20241122155432651

  • processCandidateBean方法会遍历候选bean,把带有@Controller或者@RequestMapping注解类中带有@RequestMapping注解的方法筛选出来。

image-20241122160113563

image-20241122160218188

  • 处理方法映射注册

image-20241122160659772

1.2DispatcherServlet自动配置

1.2.1自动配置类路径

image-20241122163803690

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方法。

image-20241122171626755

  • 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();
 }
  • 控制台日志开始的地方

image-20241125101741268

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("Completed 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.
             AnnotationAwareOrderComparator.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;
         }
     }
 }
  • 所有的处理器映射

image-20241121152221842

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());
             AnnotationAwareOrderComparator.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");
         }
     }
 }

image-20241121152607486

2.1.3开始请求

 // StandardWrapperValue
 public void invoke(Request request, Response response) throws IOException, ServletException {
     filterChain.doFilter(request.getRequest(), response.getResponse());
 }

image-20241125103143706

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

image-20241125105425819

  • getHandlerAdapter

image-20241125105628039

  • 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"