Java OpenResty Spring Spring Boot MySQL Redis MongoDB PostgreSQL Linux Android Nginx 面试 小程序 Arthas JVM AQS juc Kubernetes Docker 诊断工具


SpringMVC 请求流程

SpringMVC Spring 面试 评论 1 大约 17885 字

结合 Spring Boot

Spring Boot 2.6.0

流程梳理

容器初始化阶段

  • IOC容器refresh时加载自动配置类DispatcherServletAutoConfiguration
  • DispatcherServlet被注入到容器
  • RequestMappingHandlerMapping扫描所有Bean将请求映射信息等信息保存在mappingRegistry中,完成初始化后被注入到容器
  • RequestMappingHandlerAdapter请求真正执行的类被注入到容器

收到请求时

  • 第一次收到请求时会初始化DispatcherServlet相关处理器HandlerMapping等被加载到集合中
  • 然后走到真正处理执行请求的doDispatch方法中
    • 根据路径和参数等信息包装的request找到对应的RequestMappingHandlerMapping
    • 根据RequestMappingHandlerMappingHandlerMethod(包装了类对象和方法信息)找到RequestMappingHandlerAdapter
    • 执行拦截器的前置处理器
    • 反射调用方法(@Controller中的@RequestMapping方法)
    • 执行拦截器的后置处理器
    • 回调拦截器的afterCompletion

源码解析

IOC容器finishBeanFactoryInitialization阶段初始化DispatcherServletAutoConfiguration

// DispatcherServlet 自动配置类
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {

    public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";

    public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";

    @Configuration(proxyBeanMethods = false)
    @Conditional(DefaultDispatcherServletCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    @EnableConfigurationProperties(WebMvcProperties.class)
    protected static class DispatcherServletConfiguration {

        // 注册 DispatcherServlet
        @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;
        }
    }
}

Spring Boot启动时加载RequestMappingHandlerMappingRequestMappingHandlerAdapter

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

    @Configuration(proxyBeanMethods = false)
    @EnableConfigurationProperties(WebProperties.class)
    public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {

        // 存放 @RequestMapping 映射的处理映射器 RequestMappingHandlerMapping
        @Bean
        @Primary
        @Override
        public RequestMappingHandlerMapping requestMappingHandlerMapping(
                @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
                @Qualifier("mvcConversionService") FormattingConversionService conversionService,
                @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
            // Must be @Primary for MvcUriComponentsBuilder to work
            return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService, resourceUrlProvider);
        }

        // 处理 @RequestMapping 映射的处理映射器适配器 RequestMappingHandlerAdapter
        @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;
        }
    }
}

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
    @Bean
    @SuppressWarnings("deprecation")
    public RequestMappingHandlerMapping requestMappingHandlerMapping(
            @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
            @Qualifier("mvcConversionService") FormattingConversionService conversionService,
            @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {

        RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
        // ...
    }
}

创建IOC容器时,会加载RequestMappingHandlerMapping,而RequestMappingHandlerMapping父类的父类AbstractHandlerMethodMapping实现了InitializingBean

所以在Bean生命周期的initializeBean初始化阶段会调用InitializingBean接口的afterPropertiesSet

public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements MatchableHandlerMapping, EmbeddedValueResolverAware {

    @Override
    @SuppressWarnings("deprecation")
    public void afterPropertiesSet() {
        // 省略了加载配置的代码...

        // 调用父类(没复写)的父类 AbstractHandlerMethodMapping 的 afterPropertiesSet
        super.afterPropertiesSet();
    }

    @Override
    protected boolean isHandler(Class<?> beanType) {
        return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
                AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
    }

    @Override
    @Nullable
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        // 创建请求映射信息
        RequestMappingInfo info = createRequestMappingInfo(method);
        if (info != null) {
            RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
            if (typeInfo != null) {
                info = typeInfo.combine(info);
            }
            String prefix = getPathPrefix(handlerType);
            if (prefix != null) {
                info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
            }
        }
        return info;
    }

    @Nullable
    private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
        // 查找方法上是否有 @RequestMapping 注解(@GetMapping 等相关注解包含了 @RequeMapping)
        RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
        RequestCondition<?> condition = (element instanceof Class ? getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
        return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
    }

    // 创建请求映射信息
    protected RequestMappingInfo createRequestMappingInfo( RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {

        RequestMappingInfo.Builder builder = RequestMappingInfo
                .paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
                .methods(requestMapping.method())
                .params(requestMapping.params())
                .headers(requestMapping.headers())
                .consumes(requestMapping.consumes())
                .produces(requestMapping.produces())
                .mappingName(requestMapping.name());
        if (customCondition != null) {
            builder.customCondition(customCondition);
        }
        return builder.options(this.config).build();
    }
}

public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        // 调用自身方法
        initHandlerMethods();
    }

    protected void initHandlerMethods() {
        // 获取所有的 Bean
        for (String beanName : getCandidateBeanNames()) {
            if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
                // 注册
                processCandidateBean(beanName);
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }

    // 获取的是 ApplicationContext 中所有的类型(Object.class)
    protected String[] getCandidateBeanNames() {
        return (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) : obtainApplicationContext().getBeanNamesForType(Object.class));
    }

    protected void processCandidateBean(String beanName) {
        Class<?> beanType = null;
        beanType = obtainApplicationContext().getType(beanName);
        // isHandler 判断类上是不是 @Controller 或者 @RequestMapping 标注
        if (beanType != null && isHandler(beanType)) {
            // 探测 HandlerMethod
            detectHandlerMethods(beanName);
        }
    }

    protected void detectHandlerMethods(Object handler) {
        Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass());

        if (handlerType != null) {
            // 如果是代理类则获取原始类
            Class<?> userType = ClassUtils.getUserClass(handlerType);
            // 查找出所有类中包含的所有 method 并过滤出 @RequestMapping 标注的方法
            Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> {
                // 调用子类 RequestMappingHandlerMapping 实现的方法
                return getMappingForMethod(method, userType);
            });
            // 遍历找到符合的每个类
            methods.forEach((method, mapping) -> {
                Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
                // 注册到 mappingRegistry 中
                registerHandlerMethod(handler, invocableMethod, mapping);
            });
        }
    }

    // handler 类名
    protected void registerHandlerMethod(Object handler, Method method, T mapping) {
        // 将类名和方法名注册到 mappingRegistry
        this.mappingRegistry.register(mapping, handler, method);
    }
}

DispatcherServletDispatcherServletAutoConfiguration自动配置类配置中,所以是随着IOC容器创建而生成的单例Bean,但他的初始化工作是在首次请求过来时完成的。

public class DispatcherServlet extends FrameworkServlet {

    // Handler 映射集合,initStrategies 后会填充数据
    @Nullable
    private List<HandlerMapping> handlerMappings;

    @Override
    protected void onRefresh(ApplicationContext context) {
        initStrategies(context);
    }

    protected void initStrategies(ApplicationContext context) {
        // ...
        initHandlerMappings(context);
        // ...
    }

    private void initHandlerMappings(ApplicationContext context) {
        // ...
        // RequestMappingHandlerMapping、
        Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList<>(matchingBeans.values());
        }
        // ...
    }

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;

        // RequestMappingHandlerMapping
        mappedHandler = getHandler(processedRequest);

        // 获取 RequestMappingHandlerAdapter
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

        // 前置处理器,如果被拦截器拦截了就不再往下执行
        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            return;
        }

        // 真正调用方法
        // 这步方法执行完成后已经响应给调用者
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

        // 后置处理器
        mappedHandler.applyPostHandle(processedRequest, response, mv);

        // 对于 REST 请求 这步操作主要是调用拦截器的 afterCompletion 操作
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }

    // 获取 HandlerMapping 并包装为 HandlerExecutionChain 执行链
    @Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            for (HandlerMapping mapping : this.handlerMappings) {
                // 调用 AbstractHandlerMapping 中的方法,实际类型是 RequestMappingHandlerMapping
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }

    // 获取 HandlerAdapter
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        if (this.handlerAdapters != null) {
            for (HandlerAdapter adapter : this.handlerAdapters) {
                if (adapter.supports(handler)) {
                    return adapter;
                }
            }
        }
        throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }

}

public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware {
    @Override
    @Nullable
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        // 调用子类 AbstractHandlerMethodMapping 实现的方法
        Object handler = getHandlerInternal(request);
        // 添加过滤器到执行链
        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
        return executionChain;
    }
}

public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
    @Override
    @Nullable
    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        String lookupPath = initLookupPath(request);
        this.mappingRegistry.acquireReadLock();
        try {
            HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
            return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
        }
        finally {
            this.mappingRegistry.releaseReadLock();
        }
    }
}

public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
    @Override
    public final boolean supports(Object handler) {
        // handler 确实为 HandlerMethod 类型
        // supportsInternal 为子类 RequestMappingHandlerAdapter 复写的方法,一直为 true
        return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
    }

    @Override
    @Nullable
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 调用子类 RequestMappingHandlerAdapter 实现的方法
        return handleInternal(request, response, (HandlerMethod) handler);
    }
}

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {
    @Override
    protected boolean supportsInternal(HandlerMethod handlerMethod) {
        return true;
    }

    @Override
    protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        ModelAndView mav;
        // 调用自身方法
        mav = invokeHandlerMethod(request, response, handlerMethod);

        return mav;
    }

    @Nullable
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        // 包装 HandlerMethod
        ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();

        // 调用包装类 ServletInvocableHandlerMethod 中的方法,准备反射调用
        invocableMethod.invokeAndHandle(webRequest, mavContainer);

        return getModelAndView(mavContainer, modelFactory, webRequest);
    }
}

public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
    public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        // 调用父类方法,准备参数及准备反射调用
        Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
        // ...

    }
}

public class InvocableHandlerMethod extends HandlerMethod {
    @Nullable
    public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        // 获取方法参数
        Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
        // 调用自身方法
        return doInvoke(args);
    }

    @Nullable
    protected Object doInvoke(Object... args) throws Exception {
        // 获取 BridgedMethod 方法,没有 BridgedMethod 就返回原方法
        Method method = getBridgedMethod();
        // 反射调用方法
        return method.invoke(getBean(), args);
    }
}

error 控制器

spring-boot-autoconfigure-2.6.0.jar包下,默认引入SpringMVC后会加载。

package org.springframework.boot.autoconfigure.web.servlet.error;

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {

}
阅读 1965 · 发布于 2021-12-29

————        END        ————

Give me a Star, Thanks:)

https://github.com/fendoudebb

扫描下方二维码关注公众号和小程序↓↓↓

扫描二维码关注我
昵称:
  • fHLvlxbf 1楼
    e
    Chrome | Windows 10 2023-07-24
随便看看 换一批